易失性同步组合,提高性能

2022-09-04 19:56:28

使用同步时,会影响性能。易失性能否与同步结合使用,以降低性能开销?例如,计数器的实例将在许多线程之间共享,并且每个线程都可以访问计数器的公共方法。在下面的代码中,易失性用于 getter,同步用于 setter

public class Counter
{
    private volatile int count;

    public Counter()
    {
        count = 0;
    }

    public int getCount()
    {
        return count;
    }

    public synchronized void increment()
    {
        ++count;
    }   
}

请让我知道在哪种情况下这可能会中断?


答案 1

是的,你绝对可以。事实上,如果你看一下 的源代码,它本质上就是他们所做的。 简单地返回 ,这是一个(链接)。与您所做的和他们所做的唯一真正的区别是,他们使用CAS进行增量而不是同步。在现代硬件上,CAS可以消除任何互斥;在较旧的硬件上,JVM 会在增量周围放置某种互斥体。AtomicIntegerAtomicInteger.getvaluevolatile int

易失性读取与非易失性读取一样快,因此读取速度将非常快。

不仅如此,字段还保证不会撕裂:请参阅 JLS 17.7,其中指定 s 和 s 不会被撕裂。因此,您的代码将与 .volatilevolatilelongdoublelongint

正如Diego Frehner所指出的,如果你得到的值“正好”,你可能不会看到增量的结果 - 你会看到之前或之后。当然,如果已同步,则读取线程的行为完全相同 - 您将看到前增量或后增量值。所以无论哪种方式,它都是一样的。換句話說,說你不會在它發生的時候看到價值是沒有意義的 - 除非你的意思是撕裂,(a)你不會得到,(b)你永遠不會想要。get


答案 2

1.我个人已经使用过这种机制与.volatilesynchronized

2.您可以单独使用并且您将始终获得一致的结果,但仅单独使用不会始终产生相同的结果。synchronizedvolatile

3. 这是因为 volatile 关键字不是同步原语。它只是阻止缓存线程上的值,但不会阻止两个线程修改相同的值并同时将其写回。

4. 在没有锁定的情况下提供对线程的并发访问权限,但随后使用将只允许一个线程访问该线程以及类中的所有同步方法。volatilesynchronized

5.使用两者将做到这一点....volatile and synchronized

volatile -将更改的值反映到线程,并防止缓存,

synchronized -但是使用synced关键字,将确保只有一个线程获得对类的同步方法的访问权限。


推荐