多執行緒 三 執行緒安全與不安全

2021-10-06 09:21:48 字數 2522 閱讀 3153

二、解決執行緒不安全問題

如果多執行緒環境下**執行的結果是符合我們預期的,即在單執行緒環境應該的結果,則說這個程式是執行緒安全的。

例:賣票

a-1和a-2不具有原子性,導致**行之間插入了併發/並行執行的其他**(b-1)

造成的結果:業務邏輯處理出現問題

當客戶端a檢查還有一張票時,將票賣掉,還沒有執行更新資料庫時,客戶

端b檢查了票數,發現大於0,於是又賣了一-次票。然後a將票數更新回資料

庫。這是就出現了同一張票被賣了兩次。

為了提高效率,jvm在執行過程中,會盡可能的將資料在工作記憶體中執行,但這樣會造成乙個問題,共享變數在多執行緒之間不能及時看到改變,這個就是可見性問題。

例:

主記憶體sum=0;

a-1a-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的+ +操作,發生丟失)

重排序:程式執⾏的時候,cpu、編譯器可能會對執⾏順序做⼀

些調整,導致執⾏的順序並不是從上往下的。從⽽出現了⼀些意想不到的效果。執行緒內**是jvm、cpu都進行重排序,給我們的感覺是執行緒內**是有序的,是因為重排序優化方案會保證執行緒內**執行的依賴關係。

執行緒內看自己的**執行,都是有序的,但是看其他執行緒**執行,都是無序的。

如果都是私有變數,最終結果是正確的。

例:一段**是這樣的:

1.去超市買東西

2.去食堂用20分鐘吃飯

3.去超市取快遞

如果是在單執行緒情況下,jvm、cpu指令集會對其進行優化,比如,按 1->3->2的方式執行,也是沒問題,可以少跑一次超市。這種叫做指令重排序。

但在多執行緒場景下就有問題了,可能快遞是在你吃飯的20分鐘內被另乙個執行緒放過來的,或者被人變過了,如果指令重排序了,**就會是錯誤的。

jdk中有atomic包提供給我們實現原⼦性操作。

特殊的原子性**(分解執行存在編譯為class檔案時,也可能存在cpu執行命令):

(1)n++、n–、++n、–n都不是原子性:

需要分解為三條指令:從記憶體讀取變數到cpu,修改變數,寫回記憶體。

(2)物件的new操作:object obj = new object();

分解為三條指令:分配物件的記憶體、初始化物件、將物件賦值給變數。

使用volatile關鍵字:volatile是⼀種輕量級的同步機制

volatile僅僅⽤來保證該變數對所有執行緒的可⻅性,但不保證原⼦性

1.使⽤了volatile修飾的變數保證了三點:

(1)⼀旦你完成寫⼊,任何訪問這個欄位的執行緒將會得到最新的值。

(2)在你寫⼊前,會保證所有之前發⽣的事已經發⽣,並且任何更新過的資料值也是可見的,因為記憶體屏障會把之前的寫⼊值都重新整理到快取。

(3)volatile可以防⽌重排序。如果宣告了volatile,那麼cpu、編譯器就會知道這個變數是共享的,不會被快取在暫存器或者其他不可見的地方。

2.滿⾜下⾯的條件才應該使⽤volatile修飾變數:

(1)修改變數時不依賴變數的當前值(因為volatile是不保證原⼦性的)

(2)該變數不會納⼊到不變性條件中(該變數是可變的)

(3)在訪問變數的時候不需要加鎖(加鎖就沒必要使⽤volatile這種輕量級同步機制了)。volatile可以結合執行緒加鎖的一些手段,提高執行緒效率。

在多執行緒的環境下,只要我們不使⽤成員變數(不共享資料),那麼就不會出現執行緒安全的問題了。即每個執行緒都擁有⾃⼰的變數,互不⼲擾。

不可變物件⼀定執行緒安全的。

要想將物件設計成不可變物件,那麼要滿⾜下⾯三個條件:

(1)物件建立後狀態就不能修改

(2)物件所有的域都是final修飾的

(3)物件是正確建立的(沒有this引⽤逸出)

執行緒安全與執行緒不安全

執行緒安全是針對多執行緒來講的,如果所使用的公用變數在多執行緒下沒有被保護機制時,變數結果會和理論值不一致,這樣就叫作執行緒不安全,相反公用變數在保護機制下工作,就不會出現 隨機 變化,這時叫執行緒安全。執行緒安全 在多執行緒中使用時,不用自已做同步處理.執行緒不安全 在多執行緒中使用時,必須做執行...

執行緒安全與執行緒不安全

執行緒安全是針對多執行緒來講的,如果所使用的公用變數在多執行緒下沒有被保護機制時,變數結果會和理論值不一致,這樣就叫作執行緒不安全,相反公用變數在保護機制下工作,就不會出現 隨機 變化,這時叫執行緒安全。執行緒安全 在多執行緒中使用時,不用自已做同步處理.執行緒不安全 在多執行緒中使用時,必須做執行...

執行緒安全與執行緒不安全

執行緒不安全 就是不提供資料訪問保護,在多執行緒環境中對資料進行修改,會出現資料不一致的情況。執行緒安全 就是多執行緒環境中有對全域性變數的變動時,需要對執行的 塊採用鎖機制,當乙個執行緒訪問到某個資料時,其他執行緒需要等待當前執行緒執行完該 塊才可執行,不會出現資料不一致或者資料被汙染。如果一段 ...