Reputation: 2503
Please see the program below
public class TestVolatile implements Runnable {
public static volatile int counter;
public static String lock = "lock";
public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile(),"Thread-1");
Thread t2 = new Thread(new TestVolatile(),"Thread-2");
t1.start();
t2.start();
}
public void run() {
synchronized(this) {
System.out.println(Thread.currentThread()+"-"+counter);
counter++;
}
}
}
If I run this program multiple times, I get 3 different results.
first is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-0
second is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-1
third is
Thread[Thread-1,5,main]-1
Thread[Thread-2,5,main]-0
But if change the lock object from "this" to "lock", I get 2 different results
first is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-1
second is
Thread[Thread-1,5,main]-1
Thread[Thread-2,5,main]-0
My assumption when writing the program was that in either case the "counter" should never come 0 in both statements.
Can somebody explain?
Upvotes: 2
Views: 543
Reputation: 54507
It's probably not what you're looking for, but if you want to avoid the use of synchronized
and volatile
, you should use an instance of AtomicInteger
:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html
Use the getAndIncrement
method to show the same behavior as in your example.
public class TestVolatile implements Runnable {
public static AtomicInteger counter = new AtomicInteger();
public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile(),"Thread-1");
Thread t2 = new Thread(new TestVolatile(),"Thread-2");
t1.start();
t2.start();
}
public void run() {
System.out.println(Thread.currentThread() + " - " + counter.getAndIncrement());
}
}
Upvotes: 1
Reputation: 3911
You create two TestVolatile objects. The "this" keyword refers to the TestVolatile object being run in the thread. Thus you do not synchronize on the same object in the first example.
If you change the code like this, then the first example starts working:
public static void main(String[] args) {
TestVolatile testVolatile = new TestVolatile();
Thread t1 = new Thread(testVolatile,"Thread-1");
Thread t2 = new Thread(testVolatile,"Thread-2");
t1.start();
t2.start();
}
Upvotes: 3