i have two Threads that increment a shared variable x of an object myObject.
And when incrementing this number a 1000 times for each thread, i don't get 2000, i only get less.
And i know this is bad and shouldn't be done, but am just trying to figure out where is the "problem" happening in the code.
Is it because in run method myObject.x = myObject.x + 1 is entrepeted like this :
int temp = myOject.x
temp = temp + 1; //The compiler/something pauses here and goes to thread 2
myObject.x = temp; //Dind't actually get here so no incrementation ?
Or because the two threads tried to access myObject.x at the same time, so it's like only it was incremented only ones ?
the threads look like this :
public class Ex4Incr extends Thread{
private MyObject myObject;
public Ex4Incr(MyObject myObject ) {
this.myObject = myObject ;
}
#Override
public void run() {
for(int i = 0;i < 100;i++) {
myObject .setX(myObject.getX() + 1);
}
System.out.println("id:" + Thread.currentThread().getId() + " x is: " + myObject.getX());
}
}
Am sorry that i din't add code but this problem is well known but i just didn't know what expalanation is true.
Has nothing to do with the compiler. The Thread Scheduler decides which threads to run and which to pause based on a scheduling algorithm. It may suspend one thread after the variable value, say 2 is already read into temp and run the other thread instead. This thread now also reads the variable value 2 increments it to 3 and writes it back. If now the first thread continues to run it continues in the second line so temp = 2, then increments to 3 and writes it back into memory. Now we've actually performed two updates but we've done the same update twice therefore one update "got lost" if you will.
An easy way to solve this is to make your int an AtomicInteger and use its method incrementAndGet().
There are however other possibilities like using a Monitor (synchronized keyword), Lock etc. to solve the problem at hand (known as Race Condition).
Related
I am trying to create a simple Java Swing-based application that manually controls two threads which are both trying to continually increment an integer value. The application should be able to 'Start' and 'Stop' either of the threads (both threads incrementing the value simultaneously) and put either of the threads in the critical region (only one thread allowed to increment value).
Here's a screenshot of what I have, so that you may better understand what I am aiming for:
https://i.imgur.com/sQueUD7.png
I've created an "Incrementor" class which does the job of incrementing the int value, but if I try adding the synchronized keyword to the increment() method, I do not get the result I want.
private void increment() {
while (Thread.currentThread().isAlive()) {
if (Thread.currentThread().getName().equals("Thread 1")) {
if (t1Stop.isEnabled()) {
value++;
t1TextField.setText("Thread 1 has incremented value by 1. Current value = " + value + "\n");
}
} else if (Thread.currentThread().getName().equals("Thread 2")) {
if (t2Stop.isEnabled()) {
value++;
t2TextField.setText("Thread 2 has incremented value by 1. Current value = " + value + "\n");
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Any advice on how to proceed?
I hope I've made it clear what it is I am looking for, if not, let me know and I'll update this post.
your problem is the dreaded thread lock !!
but if I try adding the synchronized keyword to the increment() method, I do not get the result I want.
of course ! Thread manager changes the "Working" thread whenever he feels like it !, and you should post more code here , but from the first look , you are running the same method in both threads , so it will be dropped down to 2 case :-
the good case !
the Thread Manager changes the thread after it finishes calling the increment method(good old win win for both threads ^-^).
the bad case (and this is what you have faced)
imagine that a thread accessed the method and before completing the method the thread managers changes it and when the other method tries to access it find's a big nasty synchronized in it's face with the lock in the other thread !from here is their is no guarantee what will happen but i can assure you that 90% of this cases result's only pleases the thread manager .
The application should be able to 'Start' and 'Stop' either of the threads (both threads incrementing the value simultaneously) and put either of the threads in the critical region (only one thread allowed to increment value).
sorry to break it to you but the thread manager is not-controllable my friend .
but we can suggest a fair amount of thing's to the thread manager , so what you are trying to achieve is not possible at the java thread manager .
and stopping thread's ooky dooky , but starting a thread after stopping it is big NO !!!
from the Thread.start() documentation
It is never legal to start a thread more than once.
In particular, a thread may not be restarted once it has completed
execution.
throws IllegalThreadStateException if the thread was already
started.
here's a very rich link were you can get the topic explained more widely at the oracle's
You can use object-level lock using synchronized keyword.
=> Object-level lock : To synchronize a non static method or block so that it can be accessed by only one thread at a time for that instance. It is used to protect non static data.
Example :
public class ClasswithCriticalSections {
private AtomicInteger count = new AtomicInteger(0);
public synchronized int increment() {
count.incrementAndGet();
return count;
}
}
or
public class ClasswithCriticalSections {
Object lock1 = new Object();
Object lock2 = new Object();
private AtomicInteger count = new AtomicInteger(0);
public int increment() {
synchronized(lock1) {
count.incrementAndGet();
return count;
}
}
public int decrement() {
synchronized(lock2) {
count.addAndGet(-1);
return count;
}
}
}
Whenever I run this program it gives me different result. Can someone explain to me, or give me some topics where I could find answer in order to understand what happens in the code?
class IntCell {
private int n = 0;
public int getN() {return n;}
public void setN(int n) {this.n = n;}
}
public class Count extends Thread {
static IntCell n = new IntCell();
public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
public static void main(String[] args) {
Count p = new Count();
Count q = new Count();
p.start();
q.start();
try { p.join(); q.join(); }
catch (InterruptedException e) { }
System.out.println("The value of n is " + n.getN());
}
}
The reason is simple: you don't get and modify your counter atomically such that your code is prone to race condition issues.
Here is an example that illustrates the problem:
Thread #1 calls n.getN() gets 0
Thread #2 calls n.getN() gets 0
Thread #1 calls n.setN(1) to set n to 1
Thread #2 is not aware that thread #1 has already set n to 1 so still calls n.setN(1) to set n to 1 instead of 2 as you would expect, this is called a race condition issue.
Your final result would then depend on the total amount of race condition issues met while executing your code which is unpredictable so it changes from one test to another.
One way to fix it, is to get and set your counter in a synchronized block in order to do it atomically as next, indeed it will enforce the threads to acquire an exclusive lock on the instance of IntCell assigned to n before being able to execute this section of code.
synchronized (n) {
temp = n.getN();
n.setN(temp + 1);
}
Output:
The value of n is 400000
You could also consider using AtomicInteger instead of int for your counter in order to rely on methods of type addAndGet(int delta) or incrementAndGet() to increment your counter atomically.
The access to the IntCell n static variable is concurrent between your two threads :
static IntCell n = new IntCell();
public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
Race conditions make that you cannot have a predictable behavior when n.setN(temp + 1); is performed as it depends on which thread has previously called :temp = n.getN();.
If it the current thread, you have the value put by the thread otherwise you have the last value put by the other thread.
You could add synchronization mechanism to avoid the problem of unexpected behavior.
You are running 2 threads in parallel and updating a shared variable by these 2 threads, that is why your answer is always different. It is not a good practice to update shared variable like this.
To understand, you should first understand Multithreading and then notify and wait, simple cases
You modify the same number n with two concurrent Threads. If Thread1 reads n = 2, then Thread2 reads n = 2 before Thread2 has written the increment, Thread1 will increment n to 3, but Thread2 will no more increment, but write another "3" to n. If Thread1 finishes its incrementation before Thread2 reads, both will increment.
Now both Threads are concurrent and you can never tell which one will get what CPU cycle. This depends on what else runs on your machine. So You will always lose a different number of incrementations by the above mentioned overwriting situation.
To solve it, run real incrementations on n via n++. They go in a single CPU cycle.
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
In the following code, if i use sysout statement inside for loop then the code executes and goes inside the loop after the condition met but if i do not use sysout statement inside loop then then infinite loop goes on without entering inside the if condition even if the if condition is satisfied.. can anyone please help me to find out the exact reason for this. Just A sysout statement make the if condition to become true. why is it so?
The code is as follows:-
class RunnableDemo implements Runnable {
private Thread t;
private String threadName;
RunnableDemo( String name){
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
System.out.println("Running " + threadName );
for(;;)
{
//Output 1: without this sysout statement.
//Output 2: After uncommenting this sysout statement
//System.out.println(Thread.currentThread().isInterrupted());
if(TestThread.i>3)
{
try {
for(int j = 4; j > 0; j--) {
System.out.println("Thread: " + threadName + ", " + j);
}
} catch (Exception e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
}
}
public void start ()
{
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
static int i=0;
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i+=4;
System.out.println(i);
}
}
Output without sysout statement in the infinite loop:-
Output with sysout statement in the infinite loop:-
The problem here can be fixed by changing
static int i=0;
to
static volatile int i=0;
Making a variable volatile has a number of complex consequences and I am not an expert at this. So, I'll try to explain how I think about it.
The variable i lives in your main memory, your RAM. But RAM is slow, so your processor copies it to the faster (and smaller) memory: the cache. Multiple caches in fact, but thats irrelevant.
But when two threads on two different processors put their values in different caches, what happens when the value changes? Well, if thread 1 changes the value in cache 1, thread 2 still uses the old value from cache 2. Unless we tell both threads that this variable i might be changing at any time as if it were magic. That's what the volatile keyword does.
So why does it work with the print statement? Well, the print statement invokes a lot of code behind the scenes. Some of this code most likely contains a synchronized block or another volatile variable, which (by accident) also refreshes the value of i in both caches. (Thanks to Marco13 for pointing this out).
Next time you try to access i, you get the updated value!
PS: I'm saying RAM here, but its probably the closest shared memory between the two threads, which could be a cache if they are hyperthreaded for instance.
This is a great explanation too (with pictures!):
http://tutorials.jenkov.com/java-concurrency/volatile.html
When you are accessing a variable value, the changes aren't written to (or loaded from) the actual memory location every time. The value can be loaded into a CPU register, or cached, and sit there until the caches are flushed. Moreover, because TestThread.i is not modified inside the loop at all, the optimizer might decide to just replace it with a check before the loop, and get rid of the if statement entirely (I do not think it is actually happening in your case, but the point is that it might).
The instruction that makes the thread to flush its caches and synchronize them with the current contents of physical memory is called memory barrier. There are two ways in Java to force a memory barrier: enter or exit a synchronized block or access a volatile variable.
When either of those events happens, the cached are flushed, and the thread is guaranteed to both see an up-to-date view of the memory contents, and have all the changes it has made locally committed to memory.
So, as suggested in comments, if your declare TestThread.i as volatile, the problem will go away, because whenever the value is modified, the change will be committed immediately, and the optimizer will know not to optimizer,e the check away from the loop, and not to cache the value.
Now, why does adding a print statement changes the behaviour? Well, there is a lot of synchronization going on inside the io, the thread hits a memory barrier somewhere, and loads the fresh value. This is just a coincidence.
class Counter
{
public int i=0;
public void increment()
{
i++;
System.out.println("i is "+i);
System.out.println("i/=2 executing");
i=i+22;
System.out.println("i is (after i+22) "+i);
System.out.println("i+=1 executing");
i++;
System.out.println("i is (after i++) "+i);
}
public void decrement()
{
i--;
System.out.println("i is "+i);
System.out.println("i*=2 executing");
i=i*2;
System.out.println("i is after i*2"+i);
System.out.println("i-=1 executing");
i=i-1;
System.out.println("i is after i-1 "+i);
}
public int value()
{
return i;
} }
class ThreadA
{
public ThreadA(final Counter c)
{
new Thread(new Runnable(){
public void run()
{
System.out.println("Thread A trying to increment");
c.increment();
System.out.println("Increment completed "+c.i);
}
}).start();
}
}
class ThreadB
{
public ThreadB(final Counter c)
{
new Thread(new Runnable(){
public void run()
{
System.out.println("Thread B trying to decrement");
c.decrement();
System.out.println("Decrement completed "+c.i);
}
}).start();
}
}
class ThreadInterference
{
public static void main(String args[]) throws Exception
{
Counter c=new Counter();
new ThreadA(c);
new ThreadB(c);
}
}
In the above code, ThreadA first got access to Counter object and incremented the value along with performing some extra operations. For the very first time ThreadA does not have a cached value of i. But after the execution of i++ (in first line) it will get cache the value. Later on the value is updated and gets 24. According to the program, as the variable i is not volatile so the changes will be done in the local cache of ThreadA,
Now when ThreadB accesses the decrement() method the value of i is as updated by ThreadA i.e. 24. How could that be possible?
Assuming that threads won't see each updates that other threads make to shared data is as inappropriate as assuming that all threads will see each other's updates immediately.
The important thing is to take account of the possibility of not seeing updates - not to rely on it.
There's another issue besides not seeing the update from other threads, mind you - all of your operations act in a "read, modify, write" sense... if another thread modifies the value after you've read it, you'll basically ignore it.
So for example, suppose i is 5 when we reach this line:
i = i * 2;
... but half way through it, another thread modifies it to be 4.
That line can be thought of as:
int tmp = i;
tmp = tmp * 2;
i = tmp;
If the second thread changes i to 4 after the first line in the "expanded" version, then even if i is volatile the write of 4 will still be effectively lost - because by that point, tmp is 5, it will be doubled to 10, and then 10 will be written out.
As specified in JLS 8.3.1.4:
The Java programming language allows threads to access shared
variables (ยง17.1). As a rule, to ensure that shared variables are
consistently and reliably updated, a thread should ensure that it has
exclusive use of such variables by obtaining a lock that,
conventionally, enforces mutual exclusion for those shared variables........A field may be
declared volatile, in which case the Java Memory Model ensures that
all threads see a consistent value for the variable
Although not always but there is still a chance that the shared values among threads are not consistenly and reliably updated, which would lead to some unpredictable outcome of program. In code given below
class Test {
static int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
If, one thread repeatedly calls the method one (but no more than Integer.MAX_VALUE times in all), and another thread repeatedly calls the method two then method two could occasionally print a value for j that is greater than the value of i, because the example includes no synchronization and, the shared values of i and j might be updated out of order.
But if you declare i and j to be volatile , This allows method one and method two to be executed concurrently, but guarantees that accesses to the shared values for i and j occur exactly as many times, and in exactly the same order, as they appear to occur during execution of the program text by each thread. Therefore, the shared value for j is never greater than that for i,because each update to i must be reflected in the shared value for i before the update to j occurs.
Now i came to know that common objects (the objects that are being shared by multiple threads) are not cached by those threads. As the object is common, Java Memory Model is smart enough to identify that common objects when cached by threads could produce surprising results.
How could that be possible?
Because there is nowhere in the JLS that says values have to be cached within a thread.
This is what the spec does say:
If you have a non-volatile variable x, and it's updated by a thread T1, there is no guarantee that T2 can ever observe the change of x by T1. The only way to guarantee that T2 sees a change of T1 is with a happens-before relationship.
It just so happens that some implementations of Java cache non-volatile variables within a thread in certain cases. In other words, you can't rely on a non-volatile variable being cached.
This code should produce even and uneven output because there is no synchronized on any methods. Yet the output on my JVM is always even. I am really confused as this example comes straight out of Doug Lea.
public class TestMethod implements Runnable {
private int index = 0;
public void testThisMethod() {
index++;
index++;
System.out.println(Thread.currentThread().toString() + " "
+ index );
}
public void run() {
while(true) {
this.testThisMethod();
}
}
public static void main(String args[]) {
int i = 0;
TestMethod method = new TestMethod();
while(i < 20) {
new Thread(method).start();
i++;
}
}
}
Output
Thread[Thread-8,5,main] 135134
Thread[Thread-8,5,main] 135136
Thread[Thread-8,5,main] 135138
Thread[Thread-8,5,main] 135140
Thread[Thread-8,5,main] 135142
Thread[Thread-8,5,main] 135144
I tried with volatile and got the following (with an if to print only if odd):
Thread[Thread-12,5,main] 122229779
Thread[Thread-12,5,main] 122229781
Thread[Thread-12,5,main] 122229783
Thread[Thread-12,5,main] 122229785
Thread[Thread-12,5,main] 122229787
Answer to comments:
the index is infact shared, because we have one TestMethod instance but many Threads that call testThisMethod() on the one TestMethod that we have.
Code (no changes besides the mentioned above):
public class TestMethod implements Runnable {
volatile private int index = 0;
public void testThisMethod() {
index++;
index++;
if(index % 2 != 0){
System.out.println(Thread.currentThread().toString() + " "
+ index );
}
}
public void run() {
while(true) {
this.testThisMethod();
}
}
public static void main(String args[]) {
int i = 0;
TestMethod method = new TestMethod();
while(i < 20) {
new Thread(method).start();
i++;
}
}
}
First off all: as others have noted there's no guarantee at all, that your threads do get interrupted between the two increment operations.
Note that printing to System.out pretty likely forces some kind of synchronization on your threads, so your threads are pretty likely to have just started a time slice when they return from that, so they will probably complete the two incrementation operations and then wait for the shared resource for System.out.
Try replacing the System.out.println() with something like this:
int snapshot = index;
if (snapshot % 2 != 0) {
System.out.println("Oh noes! " + snapshot);
}
You don't know that. The point of automatic scheduling is that it makes no guarantees. It might treat two threads that run the same code completely different. Or completely the same. Or completely the same for an hour and then suddenly different...
The point is, even if you fix the problems mentioned in the other answers, you still cannot rely on things coming out a particular way; you must always be prepared for any possible interleaving that the Java memory and threading model allows, and that includes the possibility that the println always happens after an even number of increments, even if that seems unlikely to you on the face of it.
The result is exactly as I would expect. index is being incremented twice between outputs, and there is no interaction between threads.
To turn the question around - why would you expect odd outputs?
EDIT: Whoops. I wrongly assumed a new runnable was being created per Thread, and therefore there was a distinct index per thread, rather than shared. Disturbing how such a flawed answer got 3 upvotes though...
You have not marked index as volatile. This means that the compiler is allowed to optimize accesses to it, and it probably merges your 2 increments to one addition.
You get the output of the very first thread you start, because this thread loops and gives no chance to other threads to run.
So you should Thread.sleep() or (not recommended) Thread.yield() in the loop.