首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java同步计数器- get()怎么样?

Java同步计数器- get()怎么样?
EN

Stack Overflow用户
提问于 2012-10-05 00:15:26
回答 4查看 3.1K关注 0票数 3

众所周知,简单的x++不是原子操作,而实际上是读-增量-写操作。这就是为什么它应该被同步。但是get()呢?我读过它也应该是同步的,但是有人能解释一下为什么吗?通过引入happens-before关系来避免内存一致性错误?如果get()经常被多个线程调用,而值很少更改,那该怎么办呢?synchronized get()不是在拖慢他们的脚步吗?在这种情况下(不使用AtomicInteger)有没有其他实现同步的方法?volatile关键字在这里可以工作吗?

代码语言:javascript
复制
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,我的意思是在get()方法中引入该关键字并删除synchronized。我在想,如果有很多线程在读取值,而其中一个线程很少更改它,那么它是否会让它变得线程安全,而且效率也会更高。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-10-05 00:16:25

在这种情况下(不使用AtomicInteger),

有没有其他实现同步的方法?

首先,如果可以的话,你应该使用AtomicInteger。我不知道你为什么不用它。

关键字在这里会起作用吗?

是的,除了++AtomicInteger在没有锁定的情况下提供安全的增量。如果你想滚动你自己的(出于某种疯狂的原因),那么你将需要阻塞,或者你需要复制AtomicInteger内部自旋机制。

但是

()怎么办呢?我读过它也应该是同步的,但是有人能解释一下为什么吗?

AtomicInteger包装了一个volatile int以提供其功能。当您访问volatile字段时,您也跨越了get()上的内存屏障。您需要跨越内存屏障,以确保如果另一个线程更新了该值,则调用get()的线程可以看到更新。否则,线程可能正在使用过时的值。

票数 10
EN

Stack Overflow用户

发布于 2012-10-05 00:19:20

如果您重复读取非易失性值,JVM可以在寄存器中缓存该值,您可能看不到任何更改。

避免这种情况的方法是将值设为易失性。

但是,如果性能是一个问题,请使用AtomicInteger,它是无锁的。

票数 1
EN

Stack Overflow用户

发布于 2012-10-05 00:21:20

但是

()怎么办呢?我读过它也应该是同步的,但是有人能解释一下为什么吗?

假设如果get()没有同步,那么当线程执行set()操作时,任何线程都可以调用它。

现在,假设线程B正在执行set()操作,将字段a的值设置为5。一个线程在set操作完成之前读取,另一个线程在set操作之后读取。

因此,这两个线程具有不同的值。因此,它们具有不一致的字段a状态。

现在假设get()方法是同步的..然后,如果线程正在设置一个值..则除非set()操作完成,否则任何线程都不能调用get()操作。因此,每个线程都将获得相同的值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12731450

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档