public class MyThread
{
volatile static int i;
public static class myT extends Thread
{
public void run ()
{
int j = 0;
while(j<1000000){
i++;
j++;
}
}
}
public static void main (String[] argv)
throws InterruptedException{
i = 0;
Thread my1 = new myT();
Thread my2 = new myT();
my1.start();
my2.start();
my1.join();
my2.join();
System.out.println("i = "+i);
}
}
Since volatile builds happens-before relationship, the final value of i should be strictly 2000000. However, the actual result is nothing different from being without volatile for variable i. Can anyone explanation why it doesn't work here? Since i is declared volatile, it should be protected from memory inconsistency.
Can anyone explanation why it doesn't work here? Since i is declared volatile, it should be protected from memory inconsistency.
It is protected but unfortunately i++ is not an atomic operation. It is actually read/increment/store. So volatile is not going to save you from the race conditions between threads. You might get the following order of operations from your program:
thread #1 reads i, gets 10
right afterwards, thread #2 reads i, gets 10
thread #1 increments i to 11
thread #2 increments i to 11
thread #1 stores 11 to i
thread #2 stores 11 to i
As you can see, even though 2 increments have happened and the value has been properly synchronized between threads, the race condition means the value only went up by 1. See this nice looking explanation. Here's another good answer: Is a volatile int in Java thread-safe?
What you should be using are AtomicInteger which allows you to safely increment from multiple threads.
static final AtomicInteger i = new AtomicInteger(0);
...
for (int j = 0; j<1000000; j++) {
i.incrementAndGet();
}
Related
I am referencing from Baeldung.com. Unfortunately, the article does not explain why this is not a thread safe code. Article
My goal is to understand how to create a thread safe method with the synchronized keyword.
My actual result is: The count value is 1.
package NotSoThreadSafe;
public class CounterNotSoThreadSafe {
private int count = 0;
public int getCount() { return count; }
// synchronized specifies that the method can only be accessed by 1 thread at a time.
public synchronized void increment() throws InterruptedException { int temp = count; wait(100); count = temp + 1; }
}
My expected result is: The count value should be 10 because of:
I created 10 threads in a pool.
I executed Counter.increment() 10 times.
I make sure I only test after the CountDownLatch reached 0.
Therefore, it should be 10. However, if you release the lock of synchronized using Object.wait(100), the method become not thread safe.
package NotSoThreadSafe;
import org.junit.jupiter.api.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CounterNotSoThreadSafeTest {
#Test
void incrementConcurrency() throws InterruptedException {
int numberOfThreads = 10;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
CounterNotSoThreadSafe counter = new CounterNotSoThreadSafe();
for (int i = 0; i < numberOfThreads; i++) {
service.execute(() -> {
try { counter.increment(); } catch (InterruptedException e) { e.printStackTrace(); }
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
This code has both of the classical concurrency problems: a race condition (a semantic problem) and a data race (a memory model related problem).
Object.wait() releases the object's monitor and another thread can enter into the synchronized block/method while the current one is waiting. Obviously, author's intention was to make the method atomic, but Object.wait() breaks the atomicity. As result, if we call .increment() from, let's say, 10 threads simultaneously and each thread calls the method 100_000 times, we get count < 10 * 100_000 almost always, and this isn't what we'd like to. This is a race condition, a logical/semantic problem. We can rephrase the code... Since we release the monitor (this equals to the exit from the synchronized block), the code works as follows (like two separated synchronized parts):
public void increment() {
int temp = incrementPart1();
incrementPart2(temp);
}
private synchronized int incrementPart1() {
int temp = count;
return temp;
}
private synchronized void incrementPart2(int temp) {
count = temp + 1;
}
and, therefore, our increment increments the counter not atomically. Now, let's assume that 1st thread calls incrementPart1, then 2nd one calls incrementPart1, then 2nd one calls incrementPart2, and finally 1st one calls incrementPart2. We did 2 calls of the increment(), but the result is 1, not 2.
Another problem is a data race. There is the Java Memory Model (JMM) described in the Java Language Specification (JLS). JMM introduces a Happens-before (HB) order between actions like volatile memory write/read, Object monitor's operations etc. https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5 HB gives us guaranties that a value written by one thread will be visible by another one. Rules how to get these guaranties are also known as Safe Publication rules. The most common/useful ones are:
Publish the value/reference via a volatile field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5), or as the consequence of this rule, via the AtomicX classes
Publish the value/reference through a properly locked field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5)
Use the static initializer to do the initializing stores
(http://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4)
Initialize the value/reference into a final field, which leads to the freeze action (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.5).
So, to have the counter correctly (as JMM has defined) visible, we must make it volatile
private volatile int count = 0;
or do the read over the same object monitor's synchronization
public synchronized int getCount() { return count; }
I'd say that in practice, on Intel processors, you read the correct value without any of these additional efforts, with just simple plain read, because of TSO (Total Store Ordering) implemented. But on a more relaxed architecture, like ARM, you get the problem. Follow JMM formally to be sure your code is really thread-safe and doesn't contain any data races.
Why int temp = count; wait(100); count = temp + 1; is not thread-safe? One possible flow:
First thread reads count (0), save it in temp for later, and waits, allowing second thread to run (lock released);
second thread reads count (also 0), saved in temp, and waits, eventually allowing first thread to continue;
first thread increments value from temp and saves in count (1);
but second thread still holds the old value of count (0) in temp - eventually it will run and store temp+1 (1) into count, not incrementing its new value.
very simplified, just considering 2 threads
In short: wait() releases the lock allowing other (synchronized) method to run.
I just came across the synchronized block in Java and wrote a small programm to test how it works.
I create 10 threads and let each thread increment an Integer object 1000 times.
So with synchronization I would assume a result of 10000 after all threads have finished their work and a result of less than 10000 without synchronization .
However the synchronization is not wokring as I expected.
I guess it has something to do with immutability of the object or so.
My program:
public class SyncTest extends Thread{
private static Integer syncObj = new Integer(0);
private static SyncTest[] threads = new SyncTest[10];
private boolean done = false;
public void run(){
for(int i = 0; i < 1000; i++){
synchronized(syncObj){
syncObj ++;
}
}
done = true;
}
public static void main(String[] args) {
for(int i=0; i < threads.length; i++){
threads[i] = new SyncTest();
threads[i].start();
}
while(!allDone()); //wait until all threads finished
System.out.println(syncObj);
}
private static boolean allDone(){
boolean done = true;
for(int i = 0; i < threads.length; i++){
done &= threads[i].done;
}
return done;
}
}
Can someone clarify this?
syncObject is changing each time you ++ it (the ++ is converting it to a primitive int, incrementing it, and then autoboxing it back to the Integer object. Integer objects are immutable ... once they are created, they cannot change.
Bottom ine is that you are not using the same syncPObj in all the threads, different threads use different syncObjects at different times to sync on.
use one object as the synchronization (call it syncObj), and declare it as a final Object:
private static final Object syncObject = new Object();
Then your counter should be a primitive (int) for perofrmance, call it 'counter' or something.
Synchronize on syncObject, and increment counter.
Edit: as per #jsn, the done flag is also broken in that your code has a 'tight loop' on the isAllDone() method, and that is bad practice. You should use thread[i].join() to wait (blocking) on each thread's completion, and then check the status from that. Using an ExecutorService is the 'right way'.
As assumed it is because of the immutability of the Integer object.
I've changed the synchonized block to
Integer old = syncObj;
syncObj ++;
System.out.println(syncObj == old);
and my console gets filled with falses
So each time I increment the Integer a new object is createt.
Therefore I only read from the old Object and it will not be locked.
These operations are usually done with Atomic. Have a look here. These structures are specifically designed for multi-threaded computation. Normal implementations are not thread safe.
I have been working on a below sample code:
public class GlobalStatic_Multithread extends Thread{
private static int threadcounter = 0;
public void run()
{
threadcounter++ ;
System.out.println(threadcounter);
}
public static void main(String[] args) {
for(int i =0 ; i < 3 ; i++)
{
new GlobalStatic_Multithread().start();
}
System.out.println(threadcounter + " main ending");
}
}
It is very clear three threads with each having it's own lock for the class GlobalStatic_Multithread will be started. My peers explanation for this program is, After Thread-1 starts the static variable threadcounter which is an int will be incremented to value 1. Before it get's printed there is every chance OS will preempts Thread-1 and runs Thread-2, it (Thread-2) will hold value 1 for threadcounter and it will increment to 2 and it gets printed (I mean Thread-2 will print) before Thread-1 prints value of threadcounter as 2. I am very clear on this theory and I clearly know the difference between static and non-static variables. There is some subtleness which I am not able to understand how these threads getting values for threadcounter. My contention here is when Thread-1 started, it has it own local cache, so it should only look at it's own local cache unless the threadcounter is marked as volatile. When OS preempts Thread-1 just before it prints the value and let Thread-2 to run, Thread-2 incremented threadcounter to 2. How the Thread-1 got the value of threadcounter as 2 ? and Shouldn't Threads fetch values from their own cache? . Because, when OS preempts Thread-1, it is holding value of threadcounter as 1 in it's own cache and it should print threadcounter as 1. I am missing something about JVM heap and threads local cache, hence I had to post this question. I know static member variables are associated with class and they have give constant value for all objects in a program (in other words if two objects of a class using static member variable int i=0 and one object increments to i++ then second object will get the updated value, which is 1 in this case). And I also knew the static member variables are stored in heap of JVM. And also I knew when JVM starts it loads each started thread with it's own copy of cache and that cache will hold all values of the class members.
Is it possible your coming from a different language and static means something different than what you're used to? Static in Java means there is only one property for the class, hence it is shared among the instances. Try running this to see if it makes more sense.
public class GlobalStatic_Multithread extends Thread{
private static int classCounter = 0;
private int instanceCounter = 0;
public void run()
{
++classCounter;
++instanceCounter;
System.out.println("classCounter:" + classCounter + " instanceCounter:" + instanceCounter);
}
public static void main(String[] args) {
for(int i =0 ; i < 3 ; i++)
{
new GlobalStatic_Multithread().start();
}
System.out.println(threadcounter + " main ending");
}
There is a lot of flexibility in optimization that could be done by compiler and also hotspot native compilation, and you should not depend on any behavior that is not spec'd for the language. If you are doing multithreaded programming, then you should program to get the express behavior you seek.
What you are doing right now is not threadsafe and will give undetermined results.
If you want increments to the static field to always take into consideration increments already made by both this and other threads, then you COULD use synchronization, but it would be better if you used one of the atomic classes:
public class GlobalStatic_Multithread extends Thread{
private static AtomicInteger threadcounter = new AtomicInteger(); // defaults to 0
public void run()
{
int incrementedValue = threadcounter.incrementAndGet() ;
System.out.println(incrementedValue);
}
public static void main(String[] args) {
for(int i =0 ; i < 3 ; i++)
{
new GlobalStatic_Multithread().start();
}
System.out.println(threadcounter.get() + " main ending");
}
Furthermore, if you want to know that the 3 threads have finished their work before you get the value to print from main, then you should do something like this:
public class GlobalStatic_Multithread extends Thread {
private static AtomicInteger threadcounter = new AtomicInteger(); // defaults to 0
private CountDownLatch doneSignal; // This will be passed to constructor instead of
// static, to avoid race condition on construction
// of object on main thread.
public GlobalStatic_Multithread(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
public void run()
{
int incrementedValue = threadcounter.incrementAndGet() ;
System.out.println(incrementedValue);
doneSignal.countDown();
}
public static void main(String[] args) {
int threadsToStart = 3;
CountDownLatch latch = new CountDownLatch(threadsToStart );
for(int i =0 ; i < threadsToStart ; i++)
{
new GlobalStatic_Multithread(latch).start();
}
latch.await(); // waits for all threads to finish (latch value goes to 0)
System.out.println(threadcounter.get() + " main ending");
}
I just came across the synchronized block in Java and wrote a small programm to test how it works.
I create 10 threads and let each thread increment an Integer object 1000 times.
So with synchronization I would assume a result of 10000 after all threads have finished their work and a result of less than 10000 without synchronization .
However the synchronization is not wokring as I expected.
I guess it has something to do with immutability of the object or so.
My program:
public class SyncTest extends Thread{
private static Integer syncObj = new Integer(0);
private static SyncTest[] threads = new SyncTest[10];
private boolean done = false;
public void run(){
for(int i = 0; i < 1000; i++){
synchronized(syncObj){
syncObj ++;
}
}
done = true;
}
public static void main(String[] args) {
for(int i=0; i < threads.length; i++){
threads[i] = new SyncTest();
threads[i].start();
}
while(!allDone()); //wait until all threads finished
System.out.println(syncObj);
}
private static boolean allDone(){
boolean done = true;
for(int i = 0; i < threads.length; i++){
done &= threads[i].done;
}
return done;
}
}
Can someone clarify this?
syncObject is changing each time you ++ it (the ++ is converting it to a primitive int, incrementing it, and then autoboxing it back to the Integer object. Integer objects are immutable ... once they are created, they cannot change.
Bottom ine is that you are not using the same syncPObj in all the threads, different threads use different syncObjects at different times to sync on.
use one object as the synchronization (call it syncObj), and declare it as a final Object:
private static final Object syncObject = new Object();
Then your counter should be a primitive (int) for perofrmance, call it 'counter' or something.
Synchronize on syncObject, and increment counter.
Edit: as per #jsn, the done flag is also broken in that your code has a 'tight loop' on the isAllDone() method, and that is bad practice. You should use thread[i].join() to wait (blocking) on each thread's completion, and then check the status from that. Using an ExecutorService is the 'right way'.
As assumed it is because of the immutability of the Integer object.
I've changed the synchonized block to
Integer old = syncObj;
syncObj ++;
System.out.println(syncObj == old);
and my console gets filled with falses
So each time I increment the Integer a new object is createt.
Therefore I only read from the old Object and it will not be locked.
These operations are usually done with Atomic. Have a look here. These structures are specifically designed for multi-threaded computation. Normal implementations are not thread safe.
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class Main implements Runnable {
private final CountDownLatch cdl1 = new CountDownLatch(NUM_THREADS);
private volatile int bar = 0;
private AtomicInteger count = new AtomicInteger(0);
private static final int NUM_THREADS = 25;
public static void main(String[] args) {
Main main = new Main();
for(int i = 0; i < NUM_THREADS; i++)
new Thread(main).start();
}
public void run() {
int i = count.incrementAndGet();
cdl1.countDown();
try {
cdl1.await();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
bar = i;
if(bar != i)
System.out.println("Bar not equal to i");
else
System.out.println("Bar equal to i");
}
}
Each Thread enters the run method and acquires a unique, thread confined, int variable i by getting a value from the AtomicInteger called count. Each Thread then awaits the CountDownLatch called cdl1 (when the last Thread reaches the latch, all Threads are released). When the latch is released each thread attempts to assign their confined i value to the shared, volatile, int called bar.
I would expect every Thread except one to print out "Bar not equal to i", but every Thread prints "Bar equal to i". Eh, wtf does volatile actually do if not this?
It is a deliberate intention that each Thread attempts to set the value of bar at exactly the same time.
EDIT:
In light of the answer, changed code to this:
...
bar = i;
try {
Thread.sleep(0);
} catch(InterruptedException e) {
e.printStackTrace();
}
...
To ensure that a little time is wasted between the set and read of the variable.
Now the print is 50/50 on same/different value for Bar.
The JVM decides when the threads run, not you. If it felt like holding one of the ones whose latch just released for another 10ms, just because, it can do that. After the latch releases, they still have to wait for their turn to execute. Unless you're running it on a 25 core computer, they're not all assigning bar at anywhere near 'the same time' down inside the machine. Since all you're doing is a couple of primitive operations, it's extremely unlikely that one of them won't finish inside its time slice before the next one gets released!
It's not. You're misusing it. There is a great article here by Herb Sutter that explains it in more detail.
The basic idea is that volatile makes variables unoptimisable. It does not make them thread safe.
To answer the 'WTF does volatile actually do?':
volatile is all about visibility. In Java's thread model, if a thread A writes into a regular shared field, there is no guarantee that a thread B will ever see the value written by A, unless the threads are synchronized somehow. volatile is one of the synchronization mechanisms.
Unlike non-volatile fields, when thread A writes into a volatile field and thread B later reads it, B is guaranteed to see the new value and not an older version.
(Actually volatile does even more - thread B will not only see the new value of the field, but everything else written by A before it set the volatile variable as well. It established a happened-before relationship).
What you should do is replace your instance of volatile int with AtomicInteger. See here.
I think you meant to write this:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class Main implements Runnable {
private final CountDownLatch cdl1 = new CountDownLatch(NUM_THREADS);
private volatile int bar = 0;
private AtomicInteger count = new AtomicInteger(0);
private static final int NUM_THREADS = 25;
public static void main(String[] args) {
Main main = new Main();
for(int i = 0; i < NUM_THREADS; i++)
new Thread(main).start();
}
public void run() {
int i = count.incrementAndGet();
bar = i;
cdl1.countDown();
try {
cdl1.await();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if(bar != i)
System.out.println("Bar not equal to i");
else
System.out.println("Bar equal to i");
}
}
Which prints "Bar not equal to i" like you expected.