多執行緒引發資料不一致位元組碼層面理解

2021-10-11 18:49:20 字數 1528 閱讀 2492

先看一段**

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路徑下。未定義的引用...