簡體   English   中英

在讀取器/寫入器場景中,是否需要使兩個變量都可變?

[英]Do I need to make both variables volatile in reader/writer scenario?

我們有2個線程。 一個是讀者。 另一個是共享這兩個變量的writer線程:

Object data
boolean ready

我需要使兩者都不穩定嗎? 使“准備就緒”的波動性足夠嗎?

write() {
    data = <some data>
    ready = true;
}

read() {
    if (ready) {
        consume(data);
        ready = false;
    } 
}

我是否需要使兩個變量都可變?

基於對Java內存模型的有限了解,我認為我只需要使“就緒”變得易變,因為所有代碼在讀/寫“就緒”之前都會發生-在讀/寫“就緒”變量之后的代碼之前?

更新:就此問題而言,假設原子性不是問題。 數據的產生和消耗是原子的。

揮發物很適合在您使用時發出信號,但不適用於原子性。 您需要原子性,以防數據在消耗但尚未准備就緒時被更新。

正如其他人在原子性上已經明確指出的那樣,您可以通過使用ReadWriteLock來提高並發性。 有關更多詳細信息,請訪問: http : //docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html

在這種情況下,可能有多個讀取器線程,並且寫鎖將是排他的。

您的問題與SO上的另一個問題類似。

就像我在那兒說的,如果數據就緒僅由一個線程更新,那么volatile對於BOTH都可以正常工作。 原子適用於多位作者。

您的理解是正確的。

當線程1寫入volatile變量,然后線程2讀取該volatile變量時,在volatile寫入之前,線程1可見的所有變量在volatile讀取之后,對線程2可見。 就像線程1離開同步塊,然后線程2進入一樣。

但這不是提供可見性的推薦方法,因為它不會像進入/退出同步塊或獲取/釋放鎖那樣顯式地顯示自己。

易變變量對於狀態標志(如您的示例中的ready)很方便,但僅保證以線程安全的方式訪問該值,不保證其余塊按順序執行。

在您的示例中, write(data)read()操作可能會並行執行, 消費(data)的執行時間可能導致read()在第二次調用write(data)之后完成,這將導致設置ready變量即使期望對於由write(data)的第二次調用設置的新數據為true,也為false。

例如:

線程1開始: write(data1)

線程1結束://准備就緒:true,數據=數據1

線程2開始: read() //消耗(data1)需要一段時間。

線程3開始: write(data2) // ready = true,data = data2

線程2結束: read() //消耗(data2)完成,ready = false,data = data2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM