不使用 volatile 同步
synchronize without volatile
我了解 synchronize 和 volatile 的作用以及它们的使用位置。我刚刚学习了 volatile,我很困惑什么时候我们可以在没有 volatile 的情况下使用 synchronize。如果我同步一个对象,我需要阻止其他线程使用同一个对象,但在大多数情况下,我会这样做来编辑对象,如果是这样,我需要在我正在编辑的属性上具有 volatile。
以下代码是关于竞争条件的,我想知道为什么我从未见过有人在计数变量上使用 volatile :
public synchronized void add(int value){
this.count += value;
}
这里不应该算作 volatile 吗?
我只是想弄清楚可以在没有 volatile 的情况下使用 synchronize 的情况,一段代码会有所帮助。
很明显volatile
不足以实现计数器,因为它不保证原子性。但是,如果读取次数大大超过修改次数,您可以结合内部锁定和易失性变量来降低公共代码路径上的成本。检查一下,
public class Counter {
@GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
代码使用synchronized保证自增操作是原子的,使用volatile保证当前结果的可见性。如果更新不频繁,这种方法可能会执行得更好,因为读取路径上的开销只是 volatile
读取,这通常比获取锁便宜。
我了解 synchronize 和 volatile 的作用以及它们的使用位置。我刚刚学习了 volatile,我很困惑什么时候我们可以在没有 volatile 的情况下使用 synchronize。如果我同步一个对象,我需要阻止其他线程使用同一个对象,但在大多数情况下,我会这样做来编辑对象,如果是这样,我需要在我正在编辑的属性上具有 volatile。
以下代码是关于竞争条件的,我想知道为什么我从未见过有人在计数变量上使用 volatile :
public synchronized void add(int value){
this.count += value;
}
这里不应该算作 volatile 吗?
我只是想弄清楚可以在没有 volatile 的情况下使用 synchronize 的情况,一段代码会有所帮助。
很明显volatile
不足以实现计数器,因为它不保证原子性。但是,如果读取次数大大超过修改次数,您可以结合内部锁定和易失性变量来降低公共代码路径上的成本。检查一下,
public class Counter {
@GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
代码使用synchronized保证自增操作是原子的,使用volatile保证当前结果的可见性。如果更新不频繁,这种方法可能会执行得更好,因为读取路径上的开销只是 volatile
读取,这通常比获取锁便宜。