先看一段**
public
class
testsynchronized}}
; thread t2 =
newthread
("t2")}
};t1.
start()
; t2.
start()
; thread.
currentthread()
.sleep
(1000);
system.out.
println
(count);}
}
這裡使用匿名內部類的方式建立兩線程,併發修改testsynchronized.count靜態變數
編譯出的位元組碼檔案如上
testsynchronized.class main方法的位元組碼指令為:
上述指令的的意思是先new 乙個testsynchronized$1物件(也就是匿名內部類物件)壓入運算元棧中,複製乙份並壓入棧,將常量池中指向字串"t1"的引用壓入棧,呼叫testsynchronized$1的init方法(彈出棧頂的testsynchronized$1物件和"t1"),然後將建立的物件存入區域性變數表索引為1的位置,之後以同樣的方式建立testsynchronized$2,然後分別呼叫他們的start方法,最後輸出testsynchronized.count。
重點在testsynchronized$1 run方法的指令中
1:彈出棧存到區域性變數表索引為1的位置(也就是給i賦值)
2:將表索引為1位置的值壓入運算元棧
3:將1000壓入棧
6:棧頂兩數比較(即1與1000比較,1>1000的話跳轉23行,否則繼續執行)
9:獲取testsynchronized的靜態變數count,並壓入棧
12:將常量1壓入棧
13:棧頂兩數相加,並把結果壓入棧
14:將棧頂元素賦給testsynchronized的靜態變數count
17:表中索引為1位置的值自增1
20:跳轉到2
由上述指令可看出在9行中是獲取testsynchronized的count,14行將操作完的結果賦回給count。
就可能出現這種情況:假設當前count=1,執行緒1執行到了第9行獲取了count的值1,但時間片結束,執行緒2獲取時間片也執行到了第9行獲取了count的值1,然後繼續執行將操作完的值0賦給count,此時count的值為0,但執行緒1中運算元棧的值還是1,繼續執行也將操作完的結果2賦給count。此時count的值為2,這樣就發生了明明對count做了加一和減一操作,但值卻變為了2。
執行緒資料不一致例項
package kkkk public class sharedata private static class sharethread1 implements runnablecatch interruptedexception e private static class sharethread...
Redis Mysql資料不一致問題
目前各個大專案中多多少少用了寫redis快取技術,通過對redis中資料的讀取來減少對db的壓力。那麼在讀 寫兩個分離的技術中就容易造成,資料庫和快取不一致的問題 當使用者在更新資料時,在第二個步驟還未執行,但是此時又通過獲取資料介面,此時快取已經刪除,但是資料庫中還是老資料,那麼就會將老資料重新寫...
因OpenCV版本不一致所引發的報錯
目錄今天遇到了乙個很有意思的報錯。事情是這樣的,在編譯 視覺slam十四講 第12章的乙個程式時,編譯器報了 未定義的引用 的錯誤。該程式使用了dbow3這個庫,而這個庫又是依賴opencv的。dbow3這個庫經過編譯之後會生成乙個靜態鏈結庫並被安裝在 usr local lib路徑下。未定義的引用...