0

Related Java will synchronized block if changed?

 public class TestConcurrentTwo {
     public static void main(String[] args) {

         class lock {
             public Object lockObj = new Object();
             int protectedValue = 0;
         }
         lock a = new lock();

         Thread t = new Thread(() -> {
             try {
                 synchronized (a.lockObj) {
                     System.out.println("from first block start");
                     System.out.println(a.protectedValue);
                     a.lockObj = new Object();
                     Thread.sleep(1000);
                     System.out.println(a.protectedValue);
                     System.out.println("from first block done");
                 }
             } catch (InterruptedException x) {}
         });
         t.start();
         try {
             Thread.sleep(100);
         } catch (InterruptedException x) {}

         synchronized (a.lockObj) {
             System.out.println("from second block start");
             a.protectedValue++;
             System.out.println("from second block done");
         }

         System.out.println(a.protectedValue);
     }
 }

OUTPUT:

from first block start
0
from second block start
from second block done
1
1
from first block done

In the related answer, they both hold the original reference so the second block should be blocked until the completion of the first.

However, second block indeed proceeded once a.lockObj changed from first block. why?

ealeon
  • 12,074
  • 24
  • 92
  • 173
  • 1
    Your two threads are using different locks. The first thread is holding the first Object instance referenced by a,lockObj, the second thread is holding the second Object instance referenced by a.lockObj. This is easy to avoid: *do not reallocate objects you are synchronizing on*. –  May 23 '19 at 22:07
  • Some of the wording in that other answer is IMO confusing, specifically the use of the word "reference", Let us call the member ```a.lockObj``` a **reference**; the ```Object``` referenced by ```a.lockObj``` is the **referenced object**. The synchronization depends on the referenced object, not on the reference. There are two different referenced objects being used for synchronization; result misery. –  May 23 '19 at 22:12

1 Answers1

2

You are creating two objects, so let's name them for our reference:

  • ObjA created in the field initializer

  • ObjB created in the line right before sleep(1000)

The synchronized (a.lockObj) block in the thread is locking on ObjA.

Since you have sleep(100) after starting the thread, the thread will have changed a.lockObj to refer to ObjB by the time the main thread reaches its synchronized (a.lockObj) block, so that will lock on a different object.

Being a different object, the code will not block.

Hint: The lock is on the object, not the reference variable.

Andreas
  • 154,647
  • 11
  • 152
  • 247