如果在同步鎖周圍的循環(huán)中使用變量,是否將其從“主存儲(chǔ)器中刷新”讀?。?/h1>
2 回答

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超9個(gè)贊
可以更仔細(xì)地查看您的代碼,您所擁有的還不夠。對共享字段的訪問不在您的synchronized阻止范圍內(nèi),因此不行。
另外,Java要求以某種方式“同步”共享內(nèi)存的讀取和寫入。使用synchronizedkeyworld,通常意味著您需要在讀取和寫入上都使用它,而沒有顯示寫入。
除此之外,用于給定的一組字段或共享內(nèi)存的“鎖”對于讀取和寫入必須是相同的鎖。認(rèn)真地說,volatile這里要容易得多,并且其中的APIjava.util.concurrent甚至更容易推薦。不要嘗試重新發(fā)明輪子。
private static boolean flag = true; // must use 'resetFlag'
public void resetFlag() { synchronized( "lock" ) {flag = false;} }
public boolean getFlag() { synchronized( "lock" ) {return flag;} }
public void thread1() {
while ( getFlag() ){
synchronized ("lock"){
// other work
}
}
}
public static void main(String[] args) throws Exception {
Thread t1=new Thread(()->{
thread1();
});
t1.start();
Thread.sleep(1000);
resetFlag();
// The program can stop normally
}
我認(rèn)為以上已作了必要的更改。
關(guān)于第二次更新:the code on my win10+JDK8 system can stop normally 是的。不能保證內(nèi)存可見性,但不是禁止的??梢猿鲇谌魏卧蚴箖?nèi)存可見,即使只是“偶然地”。在Intel平臺(tái)上,Intel具有QPI總線,可繞過內(nèi)存總線高速交換內(nèi)存更新信息。但是即使可以通過軟件解決,所以最好只是將同步放在需要的地方(提示:請看AtomicBoolean。)。

TA貢獻(xiàn)1780條經(jīng)驗(yàn) 獲得超5個(gè)贊
由于@xTrollxDudex和@markspace提供的信息,可以從jvm級別觀察循環(huán)部分中的代碼,如果不存在事前關(guān)系,則可以從以下代碼進(jìn)行優(yōu)化:
while (flag){
synchronized (lock){
// some work
}
}
至 :
if(flag){
while (true){
synchronized (lock){
//some work
}
}
}
為了確保線程可見性,我們需要避免這種優(yōu)化,例如通過volatile關(guān)鍵字或其他同步策略。循環(huán)中同步塊的外觀類似于增強(qiáng)型volatile關(guān)鍵字的功能,它保證了變量前面的可見性,因此當(dāng)我們第二次循環(huán)進(jìn)入同步塊時(shí),可以看到最新的。所做的更改,這就是循環(huán)可以正常停止的原因??雌饋聿诲e(cuò),但這不是正確的同步方法,所以不要這樣做。
添加回答
舉報(bào)