简体   繁体   English

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

[英]volatile synchronized combination for performance

When Synchronization is used there is a performance impact. 使用同步时会对性能产生影响。 Can volatile be used in combination with synchronized to reduce the performance overhead ? volatile可以与synchronized结合使用以降低性能开销吗? For example, instance of Counter will be shared among many threads and each thread can access Counter's public methods. 例如,Counter的实例将在许多线程之间共享,每个线程都可以访问Counter的公共方法。 In the below code volatile is used for getter and synchronized is used for setter 在下面的代码中,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;
    }   
}

Please let me know in which scenario this might break ? 请告诉我这可能会破坏的情况?

Yes, you definitely can. 是的,你绝对可以。 In fact, if you look at the source code of AtomicInteger , it's essentially what they do. 事实上,如果你看一下AtomicInteger的源代码,它基本上就是他们所做的。 AtomicInteger.get simply returns value , which is a volatile int ( link ). AtomicInteger.get只返回value ,这是一个volatile int链接 )。 The only real difference from what you've done and what they do is that they use a CAS for the increment instead of synchronization. 与你所做的和他们做的唯一真正的区别是他们使用CAS来增加而不是同步。 On modern hardware, a CAS can eliminate any mutual exclusion; 在现代硬件上,CAS可以消除任何互斥; on older hardware, the JVM will put some sort of mutex around the increment. 在较旧的硬件上,JVM会在增量周围放置某种互斥。

Volatile reads are about as fast as non-volatile ones, so the reads will be quite fast. 易失性读取速度与非易失性读取速度一样快,因此读取速度非常快。

Not only that, but volatile fields are guaranteed not to tear: see JLS 17.7 , which specifies that volatile long s and double s are not subject to word tearing. 不仅如此,保证不会撕裂volatile区域:参见JLS 17.7 ,它规定了volatile long s和double s不会受到撕裂。 So your code would work with a long just as well as an int . 所以你的代码可以使用longint一样long

As Diego Frehner points out, you might not see the result of an increment if you get the value "right as" the increment happens -- you'll either see the before or the after. 正如迭戈弗雷纳所指出的那样,如果你得到增量发生的“正确”值,你可能看不到增量的结果 - 你会看到之前或之后。 Of course, if get were synchronized you'd have exactly the same behavior from the read thread -- you'd either see the before-increment or post-increment value. 当然,如果get是同步的,那么你从read线程中获得完全相同的行为 - 你要么看到前递增值或后递增值。 So it's really the same either way. 所以这两种方式都是一样的。 In other words, it doesn't make sense to say that you won't see the value as it's happening -- unless you meant word tearing, which (a) you won't get and (b) you would never want. 换句话说,说你不会看到正在发生的价值是没有意义的 - 除非你的意思是撕裂,(a)你不会得到和(b)你永远不会想要的。

1. I have personally used this mechanism of volatile combined with synchronized . 1.我曾亲自使用的这种机制volatile 联合 synchronized

2. You can alone use synchronized , and you will always get a consistent result, but using only volatile alone will Not yield the same result always. 2.可以单独使用 synchronized ,并且您将始终获得一致的结果,但仅使用 volatile 不会始终产生相同的结果。

3. This is because volatile keyword is not a synchronization primitive. 3.这是因为挥发性关键字不是原始的同步。 It merely prevents caching of the value on the thread , but it does not prevent two threads from modifying the same value and writing it back concurrently. 它只是防止在线程上缓存值 ,但它不会阻止两个线程修改相同的值并同时将其写回。

4. volatile give concurrent access to threads without lock , but then using synchronized will allow only one thread to get access to this and all the synchronized methods in the class. 4. volatile给予没有锁的线程的并发访问 ,但是然后使用synchronized允许一个线程访问该类以及类中的所有同步方法。

5. And using both volatile and synchronized will do this.... 5. 使用 volatile and synchronized都会这样做....

volatile - will reflect the changed values to thread, and prevent caching, volatile -将更改的值反映到线程,并防止缓存,

synchronized - But using synchronized keyword, will make sure that only one thread gets the access to the synchronized methods of the class. synchronized -但是使用synchronized关键字,将确保只有一个线程可以访问类的同步方法。

You will not always get the most actual count when calling getCount(). 调用getCount()时,您不会总是获得最实际的计数。 An AtomicInteger could be appropriate for you. AtomicInteger可能适合您。

There wouldn't be a performance gain from using both. 使用两者都不会带来性能提升。 Volatile guarantees that the value of a variable will be consistent when reading/writing to the variable across threads executing in parallel by preventing caching. Volatile保证在通过防止缓存并行执行的线程读取/写入变量时变量的值是一致的。 Synchronized , when applied to a method (as you do in your example), only allows a single thread to enter that method at a time and blocks others until execution is complete. 同步 ,当应用于方法时(如您的示例中所做),仅允许单个线程一次输入该方法并阻止其他方法,直到执行完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM