首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这两个示例是否等效(挥发性+同步增量与同步获取+增量)?

这两个示例是否等效(挥发性+同步增量与同步获取+增量)?
EN

Stack Overflow用户
提问于 2018-09-26 02:39:30
回答 2查看 43关注 0票数 0

我研究了synchronizedvolatile的不同之处,并编写了一个没有易失性的示例,我认为它相当于带有易失性的示例(因为在获取时需要额外的同步)。

带有易失性版本

代码语言:javascript
复制
public class Volatile extends Super {
    private volatile int xCounter;
    private volatile int yCounter;

    @Override
    public int getXCounter() {
        return this.xCounter;
    }

    @Override
    public int getYCounter() {
        return this.yCounter;
    }

    @Override
    public void incrementXCounter() {
        synchronized (getLockXCounter()) {
            this.xCounter++;
        }
    }

    @Override
    public void incrementYCounter() {
        synchronized (getLockYCounter()) {
            this.yCounter++;
        }
    }
}

没有易失性的版本

代码语言:javascript
复制
public class NonVolatile extends Super {
    private int xCounter;
    private int yCounter;

    @Override
    public int getXCounter() {
        synchronized (getLockXCounter()) {
            return this.xCounter;
        }
    }

    @Override
    public int getYCounter() {
        synchronized (getLockYCounter()) {
            return this.yCounter;
        }
    }

    @Override
    public void incrementXCounter() {
        synchronized (getLockXCounter()) {
            this.xCounter++;
        }
    }

    @Override
    public void incrementYCounter() {
        synchronized (getLockYCounter()) {
            this.yCounter++;
        }
    }
}

超类

代码语言:javascript
复制
public abstract class Super {
    private final Object lockXCounter = new Object();
    private final Object lockYCounter = new Object();

    protected abstract int getXCounter();
    protected abstract int getYCounter();
    protected abstract void incrementXCounter();
    protected abstract void incrementYCounter();

    Object getLockXCounter() {
        return lockXCounter;
    }

    Object getLockYCounter() {
        return lockYCounter;
    }
}

具体来说,在以下两点上提供的两个示例之间是否等效?

1)性能

2)线程-安全

如果在其中一个示例中没有保证线程安全,请提供一个显示线程安全不足的示例。

EN

回答 2

Stack Overflow用户

发布于 2018-09-26 02:47:21

volatile被认为是一种较弱的同步形式。在读取时,您可以使用挥发性来确保当前值的可见性,所以对所有的可变操作使用锁定,对只读操作使用易失性。在锁只允许一个线程一次访问一个值的情况下,易失性读取允许多个值,因此,当您使用易失性来保护读取的代码路径时,您将获得比对所有代码路径使用锁定时更高的共享级别。因此,前者的性能优于后者。

票数 1
EN

Stack Overflow用户

发布于 2018-09-27 08:00:36

  1. 简单地说,第一个对于作家来说是慢的,对于读者来说是快的,第二个是平衡的(假设的)。您应该注意到,在某些体系结构中,volatile与实现中的同步本质上是一样的,因为底层系统仍然需要保持内存的一致性,所以在性能方面使用这两个示例可能并不重要。尽管如此,只是我在空中挥舞着我的手,假设,你应该在你的目标系统上测试和基准测试你自己,看看你自己。现在测量,然后优化。
  2. 是的,线是安全的。首先,一致性较弱,并不总是保证看到最最新的值,因为您可能在复合更新过程中读取,但是只要作者不相互干扰,这并不重要,因为它只能是“实际”值后面的1。当然,有时强一致性很重要,所以您应该再次考虑这些因素是如何进入您自己的目标系统的。

等价物可能更难回答,但“这取决于”。同样,有时volatile与底层系统上的synchronized基本上是一样的,但这并不是真正得到JMM的保证。所保证的是,对于读者来说,写将是可见的,对于其他写,写将是原子性的(但对于读取不是这样)。

最后,您似乎受到了性能的激励,但是您应该注意到,volatile并不是免费的。再次,我应该强调,它仍然需要底层硬件的同步,无论是锁还是volatile,这都是“相对”昂贵的。

或者,您只需使用AtomicInteger,并充分利用这两种情况:快速读取和快速写入(除非在某些情况下,您应该查看LongAdder以获得高争用)。选择真的是你的。

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

https://stackoverflow.com/questions/52509179

复制
相关文章

相似问题

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