gnreddy
gnreddy

Reputation: 2503

Java Threads - Synchronized(this)

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

Answers (2)

nwinkler
nwinkler

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

Torben
Torben

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

Related Questions