相关的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);
}
}
输出:
from first block start
0
from second block start
from second block done
1
1
from first block done
在相关答案中,它们都保留了原始引用,因此应阻塞第二个块,直到第一个块完成为止。
但是,一旦a.lockObj
从第一块更改后,第二块确实开始进行。为什么?
答案 0 :(得分:3)
您正在创建两个对象,所以我们命名它们以供参考:
ObjA
sleep(1000)
之前的行中创建了ObjB
线程中的synchronized (a.lockObj)
块锁定在 ObjA 上。
由于启动线程后您拥有sleep(100)
,因此在主线程到达其a.lockObj
时,该线程将已更改synchronized (a.lockObj)
以引用 ObjB 阻止,这样将锁定在另一个对象上。
作为另一个对象,代码不会阻塞。
提示:锁位于对象上,而不是引用变量上。