簡體   English   中英

使用 volatile 變量和信號量 - Java

[英]Using volatile variables and semaphores - Java

我從線程、信號量、易失性變量等開始。我想知道當我使用信號量時是否有必要將變量定義為易失性,我的意思是:

有 2 個線程,一個增加,另一個減少變量,例如,很明顯,在每次訪問之前,我有一個互斥鎖,可以隨時控制只有一個線程在“玩”變量。

有必要定義為 volatile 嗎?

來自Semaphore 的API 文檔:

內存一致性影響:在調用“釋放”方法(如release()之前線程中的操作發生在另一個線程中成功的“獲取”方法(如acquire()之后的操作之前

所以讀/寫由信號量保護的變量是安全的。 無需將它們聲明為volatile

不應該使用信號量代替同步,因為即使初始化為一,信號量也不持有互斥互鎖,就像在某個對象上同步一樣。 確實,信號量初始化為 1,一次只允許一個線程訪問持有許可的對象。 但是持有許可的線程並不擁有它,任何其他線程都可以釋放該許可並獲得該許可。 因此,兩個線程可以同時訪問同一個對象,如果兩個線程都操作該對象,則會出現多線程問題,例如丟失更新、過時讀取等。

在您有 2 個線程的示例中,一個增加一個減少相同的變量。 互斥就足夠了,不需要 volatile 聲明。 在這里,我假設互斥是通過同步而不是信號量實現的。

volatile 不如 synchronized 嚴格,當執行的操作是原子(讀或寫)時,您可能希望使用 volatile 。 執行讀-更新-寫操作時不應使用 volatile。

我想知道當我使用信號量時是否有必要將變量定義為 volatile,

我不認為有任何這樣的限制。 互斥體是一種互斥信號量,是信號量的一種特殊變體,一次只允許一個儲物櫃。 它相當於一個計數為 1 的普通計數信號量,並且要求它只能由鎖定它的同一個線程釋放。

如果我們專門討論Java 中的信號量:信號量是許可的計數器,而獲取就像遞減,它等待而不是低於零。 它沒有上限。 正如 CIP 中提到的:

該實現沒有實際的許可對象,並且信號量不會將分配的許可與線程相關聯,因此可以從另一個線程釋放在一個線程中獲得的許可。 您可以將獲取視為使用許可,而將發布視為創建許可; 信號量不限於創建它時使用的許可數量。

對於您的場景,您可以共享一個計數器並使其可變或更好地使用AtomicInteger因為它們使用CAS機制,在低爭用下表現非常好。

暫無
暫無

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

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