synchronized keyword and locks on instance methods

I'm studying concurrency at the moment and I was learning about blocking threads.

I know that a thread can come to a blocked state when the corresponding attached task tries to access a method that is locked because another thread acquired the lock.

So from what I've read the task blocks and wait until it can access that method and so goes on with its business (namely, the rest of the run() method).

So why does this code exits like the task could call syn.getI() and access the variable in an "erroneous" state (even if the syn.manipulate() method is locked so I'm assuming the task cannot get to calling getI() ) ? where am I wrong on this?

public class SynchronizedClass {
    private int i;
    private boolean flag=true;
    public SynchronizedClass(int i){
        this.i=i;
    }
    public int getI(){
        return i;
    }
    public boolean getFlag(){
        return flag;
    }
    public synchronized void manipulate(){
        i=(i*2)+1;  //odd number
        Thread.yield();
        i= i+1; //even number       
    }
    public void close(){
        flag=false;
    }

}
public class MyThread implements Runnable {
    //auto-managed runnable
    Thread t;
    SynchronizedClass syn;
    public MyThread(SynchronizedClass syn){
        this.syn=syn;
        t=new Thread(this);
        t.start();
    }
    @Override
    public void run() {
        while(syn.getFlag()==true){
            syn.manipulate();
            if (syn.getI()%2!=0){
                syn.close();
                System.out.println("exit");
            }

        }

    }
    public static void main(String[] args) {
        SynchronizedClass syn = new SynchronizedClass(1);
        for(int i=0;i<4;++i)
            new MyThread(syn);
    }
}
Jon Skeet
people
quotationmark

even if the syn.manipulate() method is locked so I'm assuming the task cannot get to calling getI()

That's the mistake you're making, I believe.

Just because one method is synchronized doesn't implicitly mean that anything else is synchronized. It's not like one thread owning the monitor associated with an object stops other threads from accessing that object - it just stops other threads from acquiring the monitor.

If you make the getI() method synchronized, then one thread owning the monitor due to manipulate() means that other threads calling getI() on the same object would have to wait, in order to acquire the monitor.

people

See more on this question at Stackoverflow