user3725675
user3725675

Reputation: 11

Synchronized blocks don't work when using member of unrelated class as lock object?

Pretty much all resources I've found on synchronized blocks use this or a member of the class as a lock object. I'm interested in finding out why I can't get synchronized blocks to work when the lock object is a (static) member of another class. Here's my code to illustrate the problem:

public class Test {
        public static void main(String[] args) {
        Thread thread1 = new FirstThread();
        Thread thread2 = new SecondThread();
        thread1.start();
        thread2.start();
        }
    }

class FirstThread extends Thread {
    @Override
    public void run() {
        synchronized (Lock.lock) {
            System.out.println("First thread entered block");
            try {
                Lock.lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("First thread exited block");
    }
}

class SecondThread extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(1000); //just making sure second thread enters synch block after first thread
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (Lock.lock) {
            System.out.println("Second thread entered block");
            Lock.lock.notifyAll();
        }
        System.out.println("Second thread exited block");
    }
}

class Lock {
    public static Object lock = new Object();
}

My understanding is that the second thread should not be able to enter the synchronized block until the first thread exits, since they are synchronized on the same object. Thus I was expecting the program to hang (deadlock?) after "First thread entered block", since the second thread can't enter the block and the first thread will be stuck waiting for a notification. But instead I got the following output:

First thread entered block

Second thread entered block

Second thread exited block

First thread exited block

Clearly the second thread enters the synchronized block before the first thread has left it's block. Can someone explain what I'm missing? I thought the purpose of synchronized blocks was to prevent exactly this. Is it because the lock object is a member of another class?

Upvotes: 0

Views: 91

Answers (3)

Brett Okken
Brett Okken

Reputation: 6306

When you call lock.wait you "release ownership of this monitor". This allows thread 2 to enter the synchronized block.

Upvotes: 1

Lorenzo Boccaccia
Lorenzo Boccaccia

Reputation: 6151

first thread Lock.lock.wait() relinquish the lock on the synchronized object so other thread can enter the critical path and wake up the waiters.

note that sleep(), instead, does not.

Difference between wait() and sleep()

Upvotes: 3

JB Nizet
JB Nizet

Reputation: 692281

Quote from the javadoc of Object.wait():

The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method.

If that was not the case, waiting would systematically cause a deadlock, since no thread would ever be able to enter the synchronized section needed to call notify() or notifyAll(), making wait and notify completely useless.

Upvotes: 2

Related Questions