1

当我们只对变量执行读取操作时,应该使用 Volatile,因为一个线程更新的值将对另一个线程可见,即使前一个线程失去 CPU 并退出同步块。那是对的吗?当需要使用原子行为时,将使用原子原语。例如 -

if (volatileBoolean) {
    volatileBoolean = !volatileBoolean;
}

让我们假设 volatileBoolean 的值为 true。一个线程检查 volatileBoolean 为真并进入 if 块,第二个线程看到 volatileBoolean 的值为真,也进入 if 块。现在,让我们假设第一个线程将错误值(!volatileBoolean)分配给 volatileBoolean 变量并失去 CPU,因此退出 if 块。第二个线程将 volatileBoolean 视为 false,将其分配回 true。

这是应该使用 AtomicBoolean 的情况吗?如果是,为什么不能通过使用同步来处理?

synchronized(this){
        if (volatileBoolean) {
            volatileBoolean = !volatileBoolean;
        }
}
4

4 回答 4

2

这是应该使用 AtomicBoolean 的情况吗?

是的。

如果是,为什么不能通过使用同步来处理?

它在功能上是等价的,但 AtomicBoolean 不使用锁,这在适度的争用下可以更有效。请参阅this other question - 它着眼于 AtomicInteger 但结论也直接适用于 AromicBoolean 。

于 2013-06-17T18:13:17.953 回答
0

AtomicBoolean 和任何 AtomicSomething 只是使用 volatile 实现的。唯一的区别是那些 AtomicSomething 包含一些没有同步关键字的同步方法,例如 compareAndSet 或lazySet。所以你可能应该在你的情况下使用 AtomicBoolean 。

于 2015-03-25T07:01:13.867 回答
0

是的,这就是您想要使用 AtomicBoolean 的情况。这是实现您提到的那种同步(而不是自己做)的一种非常好的和安全的方法,而且速度要快得多。另请参阅此链接以与使用 volatile boolean 作为替代方法进行比较。

于 2015-01-15T01:48:19.610 回答
0

当我们只对变量执行读取操作时,应该使用 Volatile,因为一个线程更新的值将对另一个线程可见,即使前一个线程失去 CPU 并退出同步块。那是对的吗?

  • volatile 与同步块没有任何依赖关系。volatile 变量不被线程缓存。因此,一个线程的更改将对其他线程可见。
  • 因此,当对变量的写入/更新由单线程完成时,可以使用 volatile 变量,并且更新需要立即对访问该变量的所有其他线程可见。volatile 只确保可见性而不是原子性。

这是应该使用 AtomicBoolean 的情况吗?如果是,为什么不能通过使用同步来处理?

  • 是的,如果您使用同步块,我们不需要在内部使用 volatile 变量,因为同步块将确保共享数据的可见性和原子性。在大多数当前处理器架构上,易失性读取比非易失性读取稍微贵一些。

关于 AtomicBoolean

AtomicBoolean 在内部使用 volatile int 和 CAS 操作来提供可见性和原子性。

AtomicBoolean.java

public class AtomicBoolean implements java.io.Serializable {
  
  private volatile int value;

   /**
    * Creates a new {@code AtomicBoolean} with the given initial value.
    *
    * @param initialValue the initial value
    */
   public AtomicBoolean(boolean initialValue) {
       value = initialValue ? 1 : 0;
   }

来自 Java Concurrency In Practice 一书,关于 volatile 变量。

Java 语言还提供了另一种较弱的同步形式,即 volatile 变量,以确保对变量的更新可预测地传播到其他线程。当一个字段被声明为 volatile 时,编译器和运行时会注意到这个变量是共享的,并且对它的操作不应该与其他内存操作重新排序。只有在简化同步策略的实施和验证时才使用 volatile 变量;在验证正确性时避免使用 volatile 变量需要对可见性进行微妙的推理。volatile 变量的良好用途包括确保其自身状态的可见性、它们所引用的对象的可见性,或指示发生了重要的生命周期事件(例如初始化或关闭)。

于 2015-03-25T06:48:44.077 回答