[英]Synchronized and Code reorder in java
在某些鏈接中,可以認為在同步塊內可以對代碼進行重新排序,而在其他站點則無法實現。 您能舉一個例子來說明使用同步時代碼重新排序的實際情況嗎?
有兩種可能的重新排序:
但更重要的是: 如果代碼正確同步,則這些重新排序不會影響程序的執行 ,這是您應該關心的全部。
示例(所有變量本來都為0):
線程1:
a=1;
synchronized(lock) {
b=1;
c=1;
}
d=1;
線程2:
synchronized(lock) {
if (a==1) print(b); // can print 0 or 1
if (b==1) print(a)/print(c); // always prints 1
if (b==1) print(d); // can print 0 or 1
if (d==1) print(a)/print(b)/print(c); // always prints 1
}
特別是,允許將d=1
移到c=1
之前或將a=1
移到b=1
之后,因為這不是線程2能夠觀察到的,因為線程1執行的同步塊看起來像原子的從線程2操作。
另一方面,不使用相同鎖的線程將能夠觀察到這些重新排序。
只要遵守之前發生的情況,運行時就可以對操作進行重新排序。 規范寫道 :
應當指出的是,兩個動作之間存在先發生關系並不一定意味着在實現中它們必須按照該順序進行。 如果重新排序產生的結果與合法執行相符,則不合法。
和
更具體地說,如果兩個動作共享事前發生關系,則它們不一定必須按照順序與沒有事前發生關系的任何代碼發生過關系。 例如,在一個數據競爭中的一個線程中進行寫操作而在另一個線程中進行讀操作可能看起來與這些讀操作的發生順序不一致。
特別是,如果一個線程這樣做:
synchronized (lock) {
x = 1;
y = 1;
}
另一個則:
if (y == 1) System.out.println(x);
這些線程之間沒有“事前發生”的關系,另一個線程可能觀察到y
在x
被分配之前就已經被分配了,並輸出0。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.