3
votes

NOTE: Invalid question - see comment of @Bukhtoyarov Vladimir

Let's say we have the following code:

public class Main {
    private Object monitor = new Object();

    public static void main(String[] args) throws InterruptedException {
        Main main = new Main();
        main.test();
        new Thread() {
            @Override
            public void run() {
                try {
                    main.changeMonitor();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void test() throws InterruptedException {
        synchronized (monitor) {
            Thread.sleep(100);
            monitor = new Object();
            Thread.sleep(1000);
            System.out.println("test finished");

        }
    }

    private void changeMonitor() throws InterruptedException {
        Thread.sleep(600);
        monitor = new Object();
        System.out.println("monitor changed");
    }
}

Here we have two threads - main thread and another worker thread. Also we have monitor object. Inside worker thread we have next sequence of actions -

  • acquire lock on monitor
  • wait 100ms
  • assign monitor reference to point a new object
  • wait another 1000ms

In main thread we are waiting 600ms and try to reassign monitor to a new object. As the result - main thread is blocked - till worker thread releases lock on the monitor object. Here i have two questions

  1. According to the Concurrency in practice book - the only way to be blocked by the lock aquision process - is to enter synchronization block. So why main thread is blocked till worker thread releases lock - in main thread we are not trying to enter synchronization block
  2. Worker thread assign new object to monitor reference after 100ms, why main thread can not acquire lock on new reassigned object after 600ms ? I mean - after 600ms in monitor ref is new object - so lock should be ready to be gained The behavior is interesting - as i can not find any information about it in official Oracle docs or Concurrency in practice book.
1
>>> As the result - main thread is blocked - till worker thread releases lock on the monitor object. How does main thread can be blocked inside "test" method by "worker" thread, if "worker" thread started by "main" thread after main thread returns from "test" method? Looks like you posted there the code which differes from code for which you observed that main thread is blocked.Bukhtoyarov Vladimir

1 Answers

5
votes

This code

 synchronized (monitor) {

is like

Object m = monitor;
synchronized (m) {

i.e. the read only happens once, and in a context which is not thread-safe.

why main thread can not lock on new object - reassigned inside worker thread.

This means

  • once it has obtained an object to lock on to, it doesn't keep reading the latest value in a loop to see if it can lock on another object.
  • even if the reference is changed before the read, it could see an old value, as the read is not thread safe.