多執行緒 執行緒安全 volatile

2021-10-23 04:55:48 字數 1475 閱讀 7200

學習思路:

執行緒安全的三大特性

普通成員變數記憶體讀取流程

被volatile修飾後的成員變數

原子性:指定**塊是原子操作(要麼全成功要麼全失敗,不可拆分)

可見性:修改共享變數時立即同步到主記憶體,保證對其它執行緒可見,讀取共享變數時直接從主記憶體讀取

有序性:**的執行循序和語句的順序保持一致,在jvm中為了提高執行效率,允許處理器和編譯器對指令進行重排序

提到成員變數,要分為兩種情況考慮

單例(sping bean預設單例):這種情況下多執行緒公用乙個物件例項(在堆記憶體只有乙個物件例項,公用一塊記憶體空間),使用期間任何乙個執行緒對該物件進行修改,其它執行緒都可見

備註:單例情況下物件例項在堆中,之所以不被**是因為被靜態變數引用,如果引用的不是靜態變數也會被**

因為我們現在開發基本都是基於sping容器進行(大都也是單例模式),因此我們下面的講解也是基於單例模式下的成員變數展開

解釋:眾所周知執行緒處理都是在cpu上進行,圖中的執行緒a、執行緒b可理解為執行緒在cpu上執行,每個執行緒建立的時候都會有自己的私有記憶體(棧記憶體),cpu直接操作的並非我們的虛擬機器記憶體,而是計算機快取記憶體(如暫存器)然後操作棧記憶體,這裡的本地記憶體可理解為棧記憶體,主記憶體可理解為jmm堆記憶體

執行緒a寫入資料:首先將資料寫入本地記憶體,然後再寫入主記憶體

執行緒b讀資料先從本地記憶體讀取,如果沒有從主記憶體讀取,如果有直接返回

如果執行緒a修改資料同步到主記憶體後,執行緒b讀取資料發現本地記憶體有,但主記憶體的資料還沒有同步到本地記憶體,這個時候執行緒b讀到的資料仍為舊資料,從而可見性沒有得到保障

volatile關鍵字解決的問題:

可見性:如下圖執行緒在讀寫時將本地記憶體置為失效,直接讀寫主記憶體,從而保證了可見性

有序性:利用各種記憶體屏障禁止指令重排序(指令重排序時不能把後面的指令重排序到記憶體屏障之前的位置)

在每個volatile寫操作的前面插入乙個storestore屏障;

在每個volatile寫操作的後面插入乙個storeload屏障;

在每個volatile讀操作的後面插入乙個loadload屏障;

在每個volatile讀操作的後面插入乙個loadstore屏障

原子性:對volatile修飾變數的單獨讀寫有原子性,對volatile++這種復合操作(實際是先查後修改兩步操作)不具有原子性(原子操作具有原子性,復合操作不具有原子性)(如果要保證復合操作的原子性,可考慮各種鎖機制)

多執行緒 volatile

目錄 1.volatile關鍵字的兩層含義 2.volatile關鍵字的原理和實現機制 3.volatile關鍵字的使用場景 4.volatile關鍵字與synchronized關鍵字的比較 1 保證了不同執行緒對這個變數進行操作的可見性。2 禁止進行指令重排序,能在一定程度上保持有序性。volat...

多執行緒 volatile

volatile主要用途 1 保證可見性 對volatile變數的寫指令後會加入寫屏障 寫屏障 在屏障之前的對共享變數的改動都同步到主存 對volatile變數的讀指令前會加入讀屏障 讀屏障 在該屏障之後對共享變數的讀取載入的都是主存中的新資料 2 保證有序性 寫屏障保證指令重排序時,不會講寫屏障之...

多執行緒之volatile

現在進入了多核時代 程式也要發生一系列變化 比如說現在單純的變數已經不再安全了 比如說乙個int型別的資料,我們同時開了幾個執行緒在跑。現在有了乙個執行緒突然改變了該int變數,我們的意圖是幾個執行緒都要把這個變數反映出來 但是往往事與願違。讓我們來分下問題所在 int a while a 程式執行...