[英]volatile synchronized combination for performance
使用同步時會對性能產生影響。 volatile可以與synchronized結合使用以降低性能開銷嗎? 例如,Counter的實例將在許多線程之間共享,每個線程都可以訪問Counter的公共方法。 在下面的代碼中,volatile用於getter,synchronized用於setter
public class Counter
{
private volatile int count;
public Counter()
{
count = 0;
}
public int getCount()
{
return count;
}
public synchronized void increment()
{
++count;
}
}
請告訴我這可能會破壞的情況?
是的,你絕對可以。 事實上,如果你看一下AtomicInteger
的源代碼,它基本上就是他們所做的。 AtomicInteger.get
只返回value
,這是一個volatile int
( 鏈接 )。 與你所做的和他們做的唯一真正的區別是他們使用CAS來增加而不是同步。 在現代硬件上,CAS可以消除任何互斥; 在較舊的硬件上,JVM會在增量周圍放置某種互斥。
易失性讀取速度與非易失性讀取速度一樣快,因此讀取速度非常快。
不僅如此,保證不會撕裂volatile
區域:參見JLS 17.7 ,它規定了volatile
long
s和double
s不會受到撕裂。 所以你的代碼可以使用long
和int
一樣long
。
正如迭戈弗雷納所指出的那樣,如果你得到增量發生的“正確”值,你可能看不到增量的結果 - 你會看到之前或之后。 當然,如果get
是同步的,那么你從read線程中獲得完全相同的行為 - 你要么看到前遞增值或后遞增值。 所以這兩種方式都是一樣的。 換句話說,說你不會看到正在發生的價值是沒有意義的 - 除非你的意思是撕裂,(a)你不會得到和(b)你永遠不會想要的。
1.我曾親自使用的這種機制volatile
聯合 synchronized
。
2.您可以單獨使用 synchronized
,並且您將始終獲得一致的結果,但僅使用 volatile
不會始終產生相同的結果。
3.這是因為揮發性關鍵字不是原始的同步。 它只是防止在線程上緩存值 ,但它不會阻止兩個線程修改相同的值並同時將其寫回。
4. volatile
給予沒有鎖的線程的並發訪問 ,但是然后使用synchronized
將只允許一個線程訪問該類以及類中的所有同步方法。
5. 使用 volatile and synchronized
都會這樣做....
volatile
-將更改的值反映到線程,並防止緩存,
synchronized
-但是使用synchronized關鍵字,將確保只有一個線程可以訪問類的同步方法。
調用getCount()時,您不會總是獲得最實際的計數。 AtomicInteger可能適合您。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.