Can a thread change java locked object data if it is not requesting the lock itself?

Viewed 748

Oracle's tutorial Intrinsic Locks and Synchronization says:

Intrinsic[Monitor] locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state

I assumed no value in an object could be manipulated by two threads at once, should one thread be executing a 'synchronized' method.

As such, I was surprised (although relieved for the purposes of what I am looking to do) when the following code had the following output. I wasn't entirely sure what to expect, however I figured an error or some point might occur.

From what I can understand, 'synchronized' merely acts to restrict access to an object, if another thread is requesting the monitor state for that object -- but not if that other thread is altering a one off value. Is this correct?

public class HelloWorld implements Runnable{
    Thread t1;
    Thread t2;
    int val1 = 0;
    int val2 = 0;

    public static void main(String[] args) {
        HelloWorld h1 = new HelloWorld();
        h1.t1 = new Thread(h1);
        h1.t2 = new Thread(h1);
        h1.t1.start();
        h1.t2.start();
    }

    @Override
    public void run() {
        System.out.println("STARTED");
        System.gc();
        Thread currentThread = Thread.currentThread();

        if (currentThread == this.t1) { 
            this.locker(); //This is a synchronized method, incrementing val1
        }
        if (currentThread == this.t2) {
            this.adder();  //This is a non-synchronized method, incrementing val2
        }
    }

    private synchronized void locker() {
        for(int i = 0; i < 3; i++){
            val1++;
            System.out.println("LOCKER: " + this.val1);
        }
    }

    private void adder() {
        while(this.val2 < 3) {
            this.val2++;
            System.out.println("ADDER: " + this.val2);
        }
        synchronized(this) {  
        //Synchronize for final output
            System.out.println("FINAL");
            System.out.println(val1);
            System.out.println(val2);     
        }
    }

}

STARTED
STARTED
ADDER: 1
LOCKER: 1
LOCKER: 2
ADDER: 2
LOCKER: 3
ADDER: 3
FINAL
3
3
2 Answers
Related