Java的同步计数器 - 怎么样的get()?(Java synchronized counter

2019-09-23 12:54发布

据了解,简单的x++是不是一个原子操作,但实际上是只读的增量写入操作。 这就是为什么它应该是同步的。 但是,我们get() 我已阅读它也应该被同步,但可能有人解释我为什么? 通过引入避免内存一致性错误happens-before关系? 怎么样一个情况时get()是由多个线程调用非常频繁,价值很少会改变。 不synchronized get()减缓下来? 是否有任何其他的方式来实现在场景中(不使用的AtomicInteger)同步? 将volatile关键字在这里工作?

public class Counter {
    private int value;

    public synchronized int get() { return value; }
    public synchronized int increment() { return ++value; }
    public synchronized int decrement() { return --value; }
}

谢谢!

编辑:

我想讲清楚。 通过使用volatile我的意思是引入该关键字和去除synchronizedget()方法。 我在想,如果它将使线程安全的,但也更有效率,如果许多线程正在阅读的价值和一个很少改变它。

Answer 1:

是否有任何其他的方式来实现在场景中(不使用的AtomicInteger)同步?

首先,你应该使用AtomicInteger如果你能。 我不知道为什么你不会使用它。

将volatile关键字在这里工作?

除非是不是为++AtomicInteger提供了一个安全的增加而没有锁定。 如果你想推出自己的(对于一些疯狂的原因),那么你就需要阻塞或者你需要复制AtomicInteger内旋机制。

但是,我们的get()? 我已阅读它也应该被同步,但可能有人解释我为什么?

AtomicInteger包装了一个volatile int提供其功能。 当您访问volatile场你在十字架上的内存屏障get()为好。 你需要穿越该内存屏障,以确保如果另一个线程已经更新了值,线程调用get()看到更新。 否则,一个线程可以用一个过时的值来工作。



Answer 2:

如果你反复读非易失性价值,JVM可以在寄存器中缓存值,你可能看不到任何变化。

为了避免这个问题的方法是使价值波动。

然而,如果性能是一个问题,使用的AtomicInteger是锁较少。



Answer 3:

但是,我们的get()? 我已阅读它也应该被同步,但可能有人解释我为什么? 通过引入避免内存一致性错误的之前发生关系?

是的,它应该是同步的。 如果不是,可能是使用陈旧的价值,就像递增/递减会。

怎么样一个当get()方法是由多个线程调用非常频繁,价值很少会改变局面。 不同步的get()减缓下来?

无可争议的锁是非常便宜的。 即使是同时获得,成本可能没有太大影响整体性能。 volatile的作品在这里,但没有使用AtomicInteger为peformance原因可能是不必要的。

是否有任何其他的方式来实现在场景中(不使用的AtomicInteger)同步? 将volatile关键字在这里工作?

是的,我相信它会。



Answer 4:

但是,我们的get()? 我已阅读它也应该被同步,但可能有人解释我为什么?

假设如果get()是不同步的,那么任何线程将能够当某个线程执行调用它set()操作..

现在,如果假设,线程B正在执行组()操作来设置字段的值a为5。现在,假设两个纱线正在阅读的值。其中线程读取完成设定操作之前,和其他线程读取后置操作..

所以,这两个线程都不同的价值观。因此,他们有场不一致的状态a

现在假设get()方法syncrhonized。然后,如果一个线程设置的值。然后没有线程可以调用get()操作,除非set()操作完成。所以每一个线程将得到相同的值..



文章来源: Java synchronized counter - what about get()?