我研究了synchronized和volatile的不同之处,并编写了一个没有易失性的示例,我认为它相当于带有易失性的示例(因为在获取时需要额外的同步)。
带有易失性的版本
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++;
}
}
}没有易失性的版本
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++;
}
}
}超类
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)线程-安全
如果在其中一个示例中没有保证线程安全,请提供一个显示线程安全不足的示例。
发布于 2018-09-26 02:47:21
volatile被认为是一种较弱的同步形式。在读取时,您可以使用挥发性来确保当前值的可见性,所以对所有的可变操作使用锁定,对只读操作使用易失性。在锁只允许一个线程一次访问一个值的情况下,易失性读取允许多个值,因此,当您使用易失性来保护读取的代码路径时,您将获得比对所有代码路径使用锁定时更高的共享级别。因此,前者的性能优于后者。
发布于 2018-09-27 08:00:36
volatile与实现中的同步本质上是一样的,因为底层系统仍然需要保持内存的一致性,所以在性能方面使用这两个示例可能并不重要。尽管如此,只是我在空中挥舞着我的手,假设,你应该在你的目标系统上测试和基准测试你自己,看看你自己。现在测量,然后优化。等价物可能更难回答,但“这取决于”。同样,有时volatile与底层系统上的synchronized基本上是一样的,但这并不是真正得到JMM的保证。所保证的是,对于读者来说,写将是可见的,对于其他写,写将是原子性的(但对于读取不是这样)。
最后,您似乎受到了性能的激励,但是您应该注意到,volatile并不是免费的。再次,我应该强调,它仍然需要底层硬件的同步,无论是锁还是volatile,这都是“相对”昂贵的。
或者,您只需使用AtomicInteger,并充分利用这两种情况:快速读取和快速写入(除非在某些情况下,您应该查看LongAdder以获得高争用)。选择真的是你的。
https://stackoverflow.com/questions/52509179
复制相似问题