1 回答

TA貢獻(xiàn)1829條經(jīng)驗 獲得超6個贊
通過查看為類似情況生成的字節(jié)碼,我們可以看到鎖定字段的對象地址被復(fù)制并用于獲取和釋放鎖。所以原始鎖定對象用于鎖定。
在同步塊內(nèi)用新對象更改鎖定字段后,另一個線程可以獲取新對象的鎖定,并可以進(jìn)入同步代碼塊。像這樣使用同步,不提供線程之間的同步。您應(yīng)該使用另一個對象進(jìn)行鎖定。(如最終對象 cacheLock = new Object())
僅供參考,這種用法不會阻止垃圾收集。由于這里提到的對象地址在該方法的棧幀內(nèi),一旦方法執(zhí)行完畢,棧幀將被銷毀,不再保留對舊對象的引用。(但不要像這樣使用同步。)
您可以在此處查看 JVM 指令集
public class SyncTest {
private Long value;
public static void main(String[] args) {
new SyncTest().testLock();
}
public SyncTest() {
value = new Long(1);
}
private void testLock() {
synchronized (this.value) {
this.value = new Long(15);
}
}
}
private void testLock();
0 aload_0 [this]
1 getfield t1.SyncTest.value : java.lang.Long [27] // push value field to operand stack
4 dup // duplicate value field push it to operand stack
5 astore_1 // store the top of the operand stack at [1] of local variable array (which is the duplicated value field)
6 monitorenter // aquire lock on top of the operand stack
7 aload_0 [this]
8 new java.lang.Long [22]
11 dup
12 ldc2_w <Long 15> [31]
15 invokespecial java.lang.Long(long) [24]
18 putfield t1.SyncTest.value : java.lang.Long [27]
21 aload_1 // load the [1] of local variable array to the operand stack (which is the duplicated value field previously stored)
22 monitorexit // release the lock on top of the operand stack
23 goto 29
26 aload_1
27 monitorexit
.....
添加回答
舉報