併發程式設計 volatile的可見性

2021-10-21 13:45:49 字數 2136 閱讀 6500

下面的**,修改load函式中dosomething(0);傳入的值,從0到4,分別會出現能跳出迴圈和不能跳出迴圈兩種情況

0,什麼也不做,不能跳出迴圈

1,sleep,能跳出迴圈

2,使用system.out.println輸出,能跳出迴圈

3,等待10微秒,不能跳出迴圈

4,等待20微秒,能跳出迴圈

package thread;

public

class

visibilitytest

public

void

load()

system.out.

println

(thread.

currentthread()

.getname()

+"跳出迴圈:i="

+ i);}

public

void

dosomething

(int x)

catch

(interruptedexception e)

break

;case2:

// 能跳出迴圈

system.out.

println

("*****");

// synchronized

break

;case3:

// 不能跳出迴圈

shortwait

(10000);

// 10微秒

break

;case4:

// 能跳出迴圈

shortwait

(20000);

// 20微秒

break

;case0:

// 不能跳出迴圈

default

:// 不能跳出迴圈// do nothingbreak;}}

public

static

void

shortwait

(long interval)

while

(start + interval >= end);}

public

static

void

main

(string[

] args)

catch

(interruptedexception e)

對於threada,會經過read、load操作將flag讀入工作記憶體(本地記憶體),然後use操作寫入cpu core1(暫存器儲存);

對於threadb,也會有上面的步驟。但最後是寫入cpu core2(因為cpu core1一直在被占用),然後給flag賦值為false,再經過assign操作寫回工作記憶體,注意,此時不會立馬執行store、write操作,寫回主記憶體,而是在某一時刻進行;

此時,threada繼續讀取flag,是從工作記憶體中載入的,不是從主記憶體中載入的load函式中dosomething(0);傳入的值,從0到4:

• 0,什麼也不做,while(flag)一直在進行,threada的工作記憶體快取一直有效,因此一直未從主記憶體中讀取,一直是true;

• 1,sleep,會讓出cpu時間片,執行緒上下文切換(儲存現場、恢復現場),因此會從主記憶體中重新讀取flag,讀到了false則跳出迴圈;

注意:與sleep的時間沒有關係,即時sleep0ms,也會讓出cpu時間片;

• 2,使用system.out.println輸出,println方法實現內部有synchronized(this)操作,synchronized會保證可見性,因此會從主記憶體中讀取flag。讀到了false則跳出迴圈;

• 3,等待10微秒,太短了,快取未失效,因此一直未從主記憶體中讀取,一直是true;

• 4,等到20微秒,快取失效了,因此會從主記憶體中讀取,讀到了false則跳出迴圈;

以上問題歸根到底是可見性問題。當執行緒2更改了主記憶體的值後,沒有及時的讓執行緒1知道這個值被更改了。

private volatile boolean flag = true;

上述0-4,執行都會跳出迴圈。

上面例子表示了volatile關鍵字的含義之一:保證變數對所有執行緒的可見性(及時性,一但執行緒1更改了變數,執行緒2立馬知道。底層是通過快取一致性協議。)。

併發程式設計 volatile

併發程式設計中的三個概念 原子性即乙個操作或者多個操作 要麼全部執行並且執行的過程不會被任何因素打斷,要麼就都不執行 可見性指當多個執行緒訪問同乙個變數時,乙個執行緒修改了這個變數的值,其他執行緒能夠立即看得到修改的值 有序性即程式執行的順序按照 的先後順序執行 jvm在真正執行這段 的時候會保證語...

併發程式設計 可見性

這個有人看了嗎?關於volatile 併發安全 可見性的文章 只要我修改一段 加不加volatile,其結果都是一樣的,是為什麼?while getstop 給出兩個觀點 1.由於頻繁訪問stop,所以cpu會把該變數一直放到快取區域,加上volatile會把資料刷回記憶體 然而如果加上sleep ...

Java併發 volatile關鍵字 可見性

1 volatile是輕量級的synchronized,它在多處理器開發中保證了共享變數的 可見性 但無法保證 原子性 2 volatile不會引起執行緒上下文的切換,在使用恰當的情況下,比synchronized的使用和執行成本更低.volatile不需要加鎖,比synchronized更輕量級,...