整理關於線程安全的相關代碼及問題,後續補全
public class UnsafeThread {
private static final int NUM = 20;
private static final int COUNT = 10000;
private static int SUM;//int數據類型,如果值處於-128~127時,存在常量池中,如果超出範圍,處於堆中
public static void main(String[] args) {
//同時啓動20個線程,每個線程對同一個變量執行操作:循環10000次,每次循環++操作
//線程執行完畢之後,打印變量的值,檢查是否符合預期的值-> 20 0000
for(int i = 0; i < NUM; i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < COUNT; j++) {
SUM++;
}
}
});
t.start();
}
while(Thread.activeCount() > 1){
Thread.yield();
}
System.out.println(SUM);
}
//1、從主內存中講SUM變量複製到線程的工作內存
//2、在工作內存中修改變量(+1操作)
//3、將SUM變量從線程的工作內存寫回到主內存
//主內存SUM = 0;
//A-1
//A-2(+1操作---->線程A的工作內存中,SUM=1,主內存SUM=0)
//B-1(從主內存賦值SUM=0)
//B-2(+1操作---->線程B的工作內存中,SUM=1,主內存SUM=0)
//B-3(線程B中的SUM變量,將值寫回主內存SUM=1)
//A-3(線程A中的SUM變量,寫回主內存SUM=1)
//
//造成線程不安全:共享變量發生了修改的丟失(線程B的++操作,發生丟失)
//思考:出現下列兩個現象的原因是什麼??
//1、不是預期的結果20*10000
//2、每次運行結果不一樣
//答:
//一、特殊的原子代碼(分解執行存在編譯爲class問件事,也可能存在CPU執行指令):
// (1)n++,n--,++n,--n都不是原子性:
// 需要分解爲三條指令:從內存讀取變量到CPU,修改變量,寫回內存
// (2)對象的new操作
// Object obj = new Object();
// 分解爲三條指令:分配對象的內存,初始化對象,將對象賦值給變量
//二、可見性問題
//
}