final添加內存屏障問題


看了 why大佬的 博客一個困擾我122天的技術問題,我好像知道答案了。
發現他留了個坑,在變量i類型為 int 或者 Integer 時,int類型的i死循環了而Integer類型的i可以結束

int類型的i,出現死循環的機會是隨機的,可能需要多來幾次,估計1000來次吧

代碼在下面,各位大佬可以拿去測測

public class VolatileDemo {
	private static boolean flag = false;
	private static int i = 0;
	// (3)
	// private static Integer i = 0;
	// (4)
	// private volatile static int i = 0;
	
	public static void main(String[] args) throws InterruptedException {
		new Thread(() -> {
			// try {
			// 	TimeUnit.MILLISECONDS.sleep(100);
				flag = true;
				// System.out.println("flag 被修改成 true");
			// } catch (InterruptedException e) {
			// 	e.printStackTrace();
			// }
		}).start();
		while (!flag) {
			i++;
			// (1)
			// System.out.println("flag標識 = " + flag);
			// (2)
			// try {
			// 	TimeUnit.MILLISECONDS.sleep(10);
			// } catch (InterruptedException e) {
			// 	e.printStackTrace();
			// }
		}
		System.out.println("程序結束,i=" + i);
	}
	
}

當時考慮的問題是 int 類型在棧上而 Integer 類型出現在堆上,一個普通類型另一個引用類型,在群里一陣討論
最后在一個群友提示下發現了問題的關鍵,Integer 底層的 value用了 final修飾

final修飾變量,看過《java並發編程藝術》應該知道,它專門對final做了一個大章節的說明
最最重要的是它會添加內存屏障storestore,問題看起來是解決了

但新的問題出現了,還是看過《java並發編程藝術》的都知道,x86對寫寫,讀寫,讀讀內存屏障默認忽略,只對storeload有效
書本上又說道既然它加了storestore,x86無視它,那么為啥final會生效呢???

此處@why大佬過來討論討論到底怎么回事?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM