Luigi Cortese
Luigi Cortese

Reputation: 11131

Why isn't this synchronized statement example working?

Playing with synchronization, I basically have two cuncurrent threads executing a method of the same object, but probably I'm getting something wrong.

Given this piece of code

public class Test {
    public static void main(String... args) throws InterruptedException{
        new Test();
    }

    Test() throws InterruptedException{

        Stuff s = new Stuff();

        Th t1 = new Th(1,s);
        Th t2 = new Th(2,s);

        t1.start();
        Thread.sleep(1000);
        t2.start();
    }
}

class Stuff{
    public Integer count=0;

    void doStuff(int threadId){
        System.out.println(threadId + ": in doStuff");
        synchronized (count) {
            count += 100;

            if (threadId == 1) {
                try {Thread.sleep(3000);} 
                catch (InterruptedException e) {e.printStackTrace();}
            }

            System.out.println(threadId + ": count = " + count);
        }
    }
}

class Th extends Thread{

    public Stuff s;
    public int id;

    @Override
    public void run(){
        System.out.println(id+": thread run");
        s.doStuff(id);
    }

    Th(int id_,Stuff s_){
        s=s_;
        id=id_;
        System.out.println(id+": thread created");
    }
}

I get this output

    1: thread created
    2: thread created
    1: thread run
    1: in doStuff
    2: thread run
    2: in doStuff
    2: count = 200
    1: count = 200

Why is t1 printing "200"? Shouldn't t2 wait for t1 to execute the synchronized block before being able to get the lock on count and then execute the block?

Upvotes: 3

Views: 90

Answers (1)

Thilo
Thilo

Reputation: 262494

 synchronized (count) {
        count += 100;

That does not work.

You are synchronizing on Objects, not on variables or fields.

Every time you increase the count, that field will point at a different Integer object. So your synchronized block uses a different monitor all the time.

You need to find a "stable" lock object, for example

 private final Object lockMonitor = new Object();

(then you can say synchronized (lockMonitor){} instead)

Upvotes: 10

Related Questions