相关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
从第一个程序段更改起,第二个程序段便确实进行了。为什么? 最佳答案
您正在创建两个对象,因此我们将其命名为参考:
在字段初始化程序中创建的ObjA
在sleep(1000)
之前的行中创建的ObjB
线程中的synchronized (a.lockObj)
块锁定在ObjA上。
由于启动线程后已具有sleep(100)
,因此在主线程到达其a.lockObj
块时,该线程将已更改synchronized (a.lockObj)
以引用ObjB,因此它将锁定在另一个对象上。
作为另一个对象,该代码将不会阻塞。
提示:锁位于对象上,而不是引用变量上。