Concurrency in Java using synchronized blocks not giving expected results - java

Below is a trivial java program. It has a counter called "cnt" that is incremented and then added to a List called "monitor". "cnt" is incremented by multiple threads, and values are added to "monitor" by multiple threads.
At the end of the method "go()", cnt and monitor.size() should have the same value, but they don't. monitor.size() does have the correct value.
If you change the code by uncommenting one of the commented synchronized blocks, and commenting out the currently uncommented one, the code produces the expected results. Also, if you set the thread count (THREAD_COUNT) to 1, the code produces the expected results.
This can only be reproduced on a machine with multiple real cores.
public class ThreadTester {
private List<Integer> monitor = new ArrayList<Integer>();
private Integer cnt = 0;
private static final int NUM_EVENTS = 2313;
private final int THREAD_COUNT = 13;
public ThreadTester() {
}
public void go() {
Runnable r = new Runnable() {
#Override
public void run() {
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
// synchronized(cnt) {
// cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
// }
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
// synchronized(cnt) {
// cnt += NUM_EVENTS; // <-- moving the synchronized block here results in the correct value for cnt, no surprise
// }
}
};
Thread[] threads = new Thread[THREAD_COUNT];
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii] = new Thread(r);
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii].start();
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
try { threads[ii].join(); } catch (InterruptedException e) { }
}
System.out.println("Both values should be: " + NUM_EVENTS*THREAD_COUNT);
synchronized (monitor) {
System.out.println("monitor.size() " + monitor.size());
}
synchronized (cnt) {
System.out.println("cnt " + cnt);
}
}
public static void main(String[] args) {
ThreadTester t = new ThreadTester();
t.go();
System.out.println("DONE");
}
}

Ok let's have a look at the different possibilities you mention:
1.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
}
}
First the monitor object is shared between the threads, therefore getting a lock on it (that is what synchronized does) will make sure that the code inside of the block will only be executed by one thread at a time. So the 2 synchronized inside of the outer one are not necessary, the code is protected anyway.
2.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
Ok this one is a little bit tricky. cnt is an Integer object and Java does not allow modifying an Integer object (Integers are immutable) even though the code suggests that this is what is happening here. But what acutally will happen is that cnt++ will create a new Integer with the value cnt + 1 and override cnt.
This is what the code actually does:
synchronized(cnt) {
Integer tmp = new Integer(cnt + 1);
cnt = tmp;
}
The problem is that while one thread will create a new cnt object while all other threads are waiting to get a lock on the old one. The thread now releases the old cnt and will then try to get a lock on the new cnt object and get it while another thread gets a lock on the old cnt object. Suddenly 2 threads are in the critical section, executing the same code and causing a race condition. This is where the wrong results come from.
If you remove the first synchronized block (the one with monitor), then your result gets even more wrong because the chances of a race increase.
In general you should try to use synchronized only on final variables to prevent this from happening.

Related

Volatile keyword atomicity

I am trying to learn volatile field modifier in multi-threading. I came across this statement:
Volatile is preferred in cases when one thread reads and writes a shared variable and other threads just read the same. Whereas if there are more than 2 threads performing read and write both on the shared variable then only volatile is not enough, you need to have synchronization as well.
I am aware that volatile provides visibility and happens-before guarantee, but is it possible to give a simple small example of code to demonstrate the above statements wherein a synchronized block is needed?
public class TwoInts {
private volatile int i1;
private volatile int i2;
public void set(int i1, int i2) {
this.i1 = i1;
this.i2 = i2;
}
public boolean same() {
return i1 == i2;
}
}
Now, if you have one thread doing this:
while (true) {
twoInts.set(i, i);
i++;
}
and a second thread doing this:
while (true) {
if (!twoInts.same()) {
System.out.println("Ooops!!");
}
}
then you will observe the problem that the quoted text is talking about. And if you rewrite the TwoInts class to make the methods synchronized then the "Oooops!!" messages will stop.
Let's say you have int i and two threads, you expect every one read i and set i = i + 1.
Like this:
public class Main {
private static volatile int i = 0;
public static void main(String[] args) throws Exception{
Runnable first = new Runnable() {
#Override
public void run() {
System.out.println("Thread_1 see i = " + i);
i++;
System.out.println("Thread_1 set i = " + i);
}
};
Runnable second = new Runnable() {
#Override
public void run() {
System.out.println("Thread_2 see i = " + i);
i++;
System.out.println("Thread_2 set i = " + i);
}
};
new Thread(first).start();
new Thread(second).start();
}
}
The result is:
Thread_1 see i = 0
Thread_2 see i = 0
Thread_1 set i = 1
Thread_2 set i = 2
As you see, Thread_2 get 0 and set 2(because Thread_1 has updated i to 1), which is not expected.
After adding syncronization,
public class Main {
private static volatile int i = 0;
public static void main(String[] args) throws Exception{
Runnable first = new Runnable() {
#Override
public void run() {
synchronized (Main.class) {
System.out.println("Thread_1 see i = " + i);
i++;
System.out.println("Thread_1 set i = " + i);
}
}
};
Runnable second = new Runnable() {
#Override
public void run() {
synchronized (Main.class) {
System.out.println("Thread_2 see i = " + i);
i++;
System.out.println("Thread_2 set i = " + i);
}
}
};
new Thread(first).start();
new Thread(second).start();
}
}
It works:
Thread_2 see i = 0
Thread_2 set i = 1
Thread_1 see i = 1
Thread_1 set i = 2
There are a lot of such examples... Here's one:
volatile int i = 0;
// Thread #1
while (true) {
i = i + 1;
}
// Thread #2
while (true) {
Console.WriteLine(i);
}
In this case, Thread #1 and Thread #2 are both reading the variable i, but only Thread #1 is writing to it. Thread #2 will always see an incrementing value of i.
Without the volatile keyword, you will occasionally see strange behavior, usually on multiprocessor machines or multicore CPUs. What happens (simplifying slightly here) is that Thread #1 and #2 are each running on their own CPU and each gets it's own copy of i (in it's CPU cache and/or registers). Without the volatile keyword, they may never update each other about the changed value.
Contrast with this example:
static volatile int i = 0;
// Thread #1
while (true) {
i = i + 1;
}
// Thread #2
while (true) {
if (i % 2 == 0)
i == 0;
else
Console.WriteLine(i);
}
So here, Thread #1 is trying to monotonically increment i, and Thread #2 is either going to set i to 0 (if i is even) or print it to the console if i is odd. You would expect that Thread #2 could never print an even number to the console, right?
It turns out that that is not the case. Because you have no synchronization around the access to i, it is possible that Thread #2 sees an odd value, moves to the else branch, and then Thread #1 increments the value of i, resulting in Thread #2 printing an even number.
In this scenario, one way of addressing the problem is to use basic locking as a form of synchronization. Because we cannot lock on a primitive, we introduce a blank Object to lock on:
static volatile int i = 0;
static Object lockOnMe = new Object();
// Thread #1
while (true) {
lock (lockOnMe) {
i = i + 1;
}
}
// Thread #2
while (true) {
lock (lockOnMe) {
if (i % 2 == 0)
i == 0;
else
Console.WriteLine(i);
}
}

Thread.sleep blocks other Thread

I have a Output class which just prints everything that it gets to print.
public class Output {
private static List<String> textList = new ArrayList<>();
private static Output output = null;
private Output() {
Runnable task = () -> {
int lastIndex = 0;
while (true) {
while (lastIndex < textList.size()) {
System.out.println(lastIndex + " - " + textList.size() + ": " + textList.get(lastIndex));
outputText(textList.get(lastIndex));
lastIndex ++;
}
}
};
new Thread(task).start();
}
private static void outputText(String text) {
synchronized (System.out) {
System.out.println(text);
}
}
public static void say(String text) {
if (output == null) {
output = new Output();
}
textList.add(text);
}
}
When I add something to print, everything works fine:
for (int i = 0; i < 10; i++) {
Output.say("" + i);
}
But when I add a Thread.sleep to the loop it stops on the first output:
for (int i = 0; i < 10; i++) {
Output.say("" + i);
Thread.sleep(100);
}
How can I prevent it? I mean, I'm stopping with sleep just the main thread and not the separate thread.
When you don’t synchronize threads correctly, there is no guaranty that threads see updates made by other threads. They may either completely miss updates or see only parts of them, creating an entirely inconsistent result. Sometimes they may even appear to do the right thing. Without proper synchronization (in the sense of any valid construct specified to be thread safe), this is entirely unpredictable.
Sometimes, the chances of seeing a particular behavior are higher, like in your example. In most runs, the loop without sleep will complete before the other thread even starts its work, whereas inserting sleep raises the chance of lost updates after the second thread has seen values. Once the second thread has seen a value for textList.size(), it might reuse the value forever, evaluating lastIndex < textList.size() to false and executing the equivalent of while(true) { }.
It’s funny that the only place where you inserted a construct for thread safety, is the method outputText that is called by a single thread only (and printing to System.out is synchronized internally in most environments anyway).
Besides, it’s not clear why you are creating an object of type Output that has no relevance here, as all fields and methods are static.
Your code can be corrected and simplified to
public static void main(String[] args) throws InterruptedException {
List<String> textList = new ArrayList<>();
new Thread( () -> {
int index=0;
while(true) synchronized(textList) {
for(; index<textList.size(); index++)
System.out.println(textList.get(index));
}
}).start();
for (int i = 0; i < 10; i++) {
synchronized(textList) {
textList.add(""+i);
}
Thread.sleep(100);
}
}
though it still contains the issues of you original code of never terminating due to the infinite second thread and also burning the CPU with a polling loop. You should let the second thread wait for new items and add a termination condition:
public static void main(String[] args) throws InterruptedException {
List<String> textList = new ArrayList<>();
new Thread( () -> {
synchronized(textList) {
for(int index=0; ; index++) {
while(index>=textList.size()) try {
textList.wait();
} catch(InterruptedException ex) { return; }
final String item = textList.get(index);
if(item==null) break;
System.out.println(item);
}
}
}).start();
for (int i = 0; i < 10; i++) {
synchronized(textList) {
textList.add(""+i);
textList.notify();
}
Thread.sleep(100);
}
synchronized(textList) {
textList.add(null);
textList.notify();
}
}
This is still only an academic example that you shouldn’t use in real life code. There are classes for thread safe data exchange provided by the Java API removing the burden of implementing such things yourself.
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
String endMarker = "END-OF-QUEUE"; // the queue does not allow null
new Thread( () -> {
for(;;) try {
String item = queue.take();
if(item == endMarker) break;// don't use == for ordinary strings
System.out.println(item);
} catch(InterruptedException ex) { return; }
}).start();
for (int i = 0; i < 10; i++) {
queue.put(""+i);
Thread.sleep(100);
}
queue.put(endMarker);
}

can ayone what is happening at the background

package workouts;
public class synchro {
private int count = 0;
public void counting() {
Thread T1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
Thread T2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
but when introduced a synchronised method and call it inside run method like below.. the output is 20000 for how many times if u run it..can someone explain the difference between the above and below code
public class synchro {
private int count = 0;
public synchronized void dosinglethread(){
count++;
}
public void counting() {
Thread T1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
Thread T2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
When you say count++, three things happen:
The current value of count is retrieved by the VM
The VM increments the value by 1
The new value is put back into count
It's entirely possible that T1 and T2 both get the value of count, then increment it separately, and then but back the result, like so:
Timeslot T1 T2
1 count = 3 ----
2 ---- count = 3
3 3 + 1 = 4 ----
4 ---- 3 + 1 = 4
5 store 4 in count ----
6 ---- store 4 in count
So now, count++ has been called twice, but the value has only increased by one. To prevent this, you have to make the increment atomic. Atomic means that either the entire sequence of operations is executed, or none of it is. Simply put, if two statements are synchronized on the same Object, they will not interleave.
In your second piece of code, dosinglethread() is declared synchronized. This is the equivalent of:
public void dosinglethread() {
synchronized (this) {
count++;
}
}
This means that when one of the threads starts executing it, they acquire a lock on your synchro instance. When the second thread also tries to execute the method, it will see that another thread already owns the lock on this, so it has to wait. When the first thread completes the method, it will release the lock and the other thread can then take it.
So why didn't volatile work? volatile variables will not cause threads to wait until they are available. Instead, when count is volatile and you call count++, the following happens: (Code adapted from Javamex's Tutorial)
int temp;
synchronized (count) {
temp = count;
}
temp = temp + 1;
synchronized (count) {
count = temp;
}
Note that this code is for illustration only: synchronized can not be used on primitives.
It's clear, then, that the threads might still be paused at temp = temp + 1, giving the same problems as when you don't do any synchronization.
For more information, check the tutorial I mentioned.

Sequential execution of threads using synchronized

I have a snippet of code that creates 3 threads and expect them to print sequentially using synchronized block on the integer object. But apparently I am getting deadlock sometimes. See below:
public class SequentialExecution implements Runnable {
private Integer i = 1;
public void run() {
String tmp = Thread.currentThread().getName();
if (tmp.equals("first")) {
synchronized(i) {
first();
i = 2;
}
} else if (tmp.equals("second")) {
while (i != 2);
synchronized(i) {
second();
i = 3;
}
} else {
while (i != 3);
synchronized(i) {
third();
}
}
}
public void first() {
System.out.println("first " + i);
}
public void second() {
System.out.println("second " + i);
}
public void third() {
System.out.println("third " + i);
}
public static void main(String[] args) {
//create 3 threads and call first(), second() and third() sequentially
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
}
}
The result I am expecting(and sometimes getting) is:
first 1
second 2
third 3
One sample result I am getting with deadlock(and eclipse hangs) is:
first 1
second 2
Anyone know why this is not working? I know I can use locks but I just don't know why using synchronized block is not working.
Declare i to be volatile: private volatile Integer i = 1;. This warns the compiler that it must not apply certain optimizations to i. It must be read from memory each time it is referenced in case another thread has changed it.
I also agree with the recommendation in user3582926's answer to synchronize on this rather than i, because the object referenced by i changes as the program runs. It is neither necessary nor sufficient to make the program work, but it does make it a better, clearer program.
I have tested each change by changing the main method to:
public static void main(String[] args) throws InterruptedException {
// create 3 threads and call first(), second() and third() sequentially
for (int i = 0; i < 1000; i++) {
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
t1.join();
t2.join();
t3.join();
}
}
There is no deadlock. There is a memory order issue.
The while loops in the second and third threads are outside any synchronized block. There is nothing telling the compiler and JVM that those threads cannot keep i, or the object to which it points, in a register or cache during the loop. The effect is that, depending on timing, one of those threads may get stuck looping looking at a value that is not going to change.
One way to solve the problem is to mark i volatile. That warns the compiler that it is being used for inter-thread communication, and each thread needs to watch for changes in memory contents whenever i changes.
In order to solve it entirely using synchronization, you need to check the value of the Integer referenced by i inside a block that is synchronized on a single, specific object. i is no good for that, because it changes due to boxing/unboxing conversion. It might as well be a simple int.
The synchronized blocks cannot wrap the while loops, because that really would lead to deadlock. Instead, the synchronized block has to be inside the loop. If the updates to i are synchronized on the same object, that will force the updates to be visible to the tests inside the while loops.
These considerations lead to the following synchronization-based version. I am using a main method that does 1000 runs, and will itself hang if any thread in any of those runs hangs.
public class SequentialExecution implements Runnable {
private int i = 1;
public void run() {
String tmp = Thread.currentThread().getName();
if (tmp.equals("first")) {
synchronized (this) {
first();
i = 2;
}
} else if (tmp.equals("second")) {
while (true) {
synchronized (this) {
if (i == 2) {
break;
}
}
}
synchronized (this) {
second();
i = 3;
}
} else {
while (true) {
synchronized (this) {
if (i == 3) {
break;
}
}
}
synchronized (this) {
third();
}
}
}
public void first() {
System.out.println("first " + i);
}
public void second() {
System.out.println("second " + i);
}
public void third() {
System.out.println("third " + i);
}
public static void main(String[] args) throws InterruptedException {
// create 3 threads and call first(), second() and third() sequentially
for (int i = 0; i < 1000; i++) {
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
t1.join();
t2.join();
t3.join();
}
}
}
I believe you want to be using synchronized(this) instead of synchronized(i).

how do I set up the following thread in Java?

I have a thread with the following form:
each execution of each thread is supposed to run a function in the class. That function is completely safe to run by itself. The function returns a value, say an int.
After all threads have been executed, the function values need to be accumulated.
So, it goes (in pseudo-code) something like that:
a = 0
for each i between 1 to N
spawn a thread independently and call the command v = f(i)
when thread finishes, do safely: a = a + v
end
I am not sure how to use Java in that case.
The problem is not creating the thread, I know this can be done using
new Thread() {
public void run() {
...
}
}
the problem is accumulating all the answers.
Thanks for any info.
I would probably do something like:
public class Main {
int a = 0;
int[] values;
int[] results;
public Main() {
// Init values array
results = new int[N];
}
public int doStuff() {
LinkedList<Thread> threads = new LinkedList<Thread>();
for (final int i : values) {
Thread t = new Thread() {
public void run() {
accumulate(foo(i));
}
};
threads.add(t);
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
// Act accordingly, maybe ignore?
}
}
return a;
}
synchronized void accumulate(int v) {
// Synchronized because a += v is actually
// tmp = a + v;
// a = tmp;
// which can cause a race condition AFAIK
a += v;
}
}
Use an ExecutorCompletionService, Executor, and Callable.:
Start with a Callable that calls your int function:
public class MyCallable implements Callable<Integer> {
private final int i;
public MyCallable(int i) {
this.i = i;
}
public Integer call() {
return Integer.valueOf(myFunction(i));
}
}
Create an Executor:
private final Executor executor = Executors.newFixedThreadPool(10);
10 is the maximum number of threads to execute at once.
Then wrap it in an ExecutorCompletionService and submit your jobs:
CompletionService<Integer> compService = new ExecutionCompletionService<Integer>(executor);
// Make sure to track the number of jobs you submit
int jobCount;
for (int i = 0; i < n; i++) {
compService.submit(new MyCallable(i));
jobCount++;
}
// Get the results
int a = 0;
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
}
ExecutorCompletionService allows you to pull tasks off of a queue as they complete. This is a little different from joining threads. Although the overall outcome is the same, if you want to update a UI as the threads complete, you won't know what order the threads are going to complete using a join. That last for loop could be like this:
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
updateUi(a);
}
And this will update the UI as tasks complete. Using a Thread.join won't necessarily do this since you'll be getting the results in the order that you call the joins, not the order that the threads complete.
Through the use of the executor, this will also allow you to limit the number of simultaneous jobs you're running at a given time so you don't accidentally thread-bomb your system.

Categories

Resources