0

我的理解:声明一个变量volatile可以保证其他线程对该变量的写入可见性。本质上,每个writevolatile 变量都发生在后续reads.

我了解它的原子性AtomicBoolean.compareAndSet()以及它如何提供不提供的read+write操作的原子性volatile。但我没有看到任何文档通过以下方式提供可见性保证AtomicBoolean

  1. 每个成功write的 byAtomicBoolean.compareAndSet() 最终都会对后续线程AtomicBoolean.get()AtomicBoolean.compareAndSet()其他线程可见。

但是,我一直看到标记为thread-safe这样的代码,

// default false so that first-thread that execute() can enter the logic block
private static final  AtomicBoolean executing = new AtomicBoolean(false);


public void execute() {
    if (executing.compareAndSet(false, true)) {  // check if the executing is previously false and if so update it to true
        try {
            // thead-safe code, i.e only one thread guaranteed to execute at any point of time time
        } finally {
            executing.set(false); // executing thread now re-sets the test value
        }
    }
}

变量不应该executing也声明volatileprivate static volatile AtomicBoolean executing = new AtomicBoolean(false);?那么所需要的可见性保证AtomicBoolean就实现了吗?

4

2 回答 2

3

AtomicBoolean是否也需要制作volatile

不。

在示例中,executing声明为static final,因此它将在类初始化时初始化一次,并安全地发布到需要它的任何其他代码。

这种行为是有保证的,因为在类初始化完成(通常)和随后使用该类声明的任何静态变量之间存在发生之前。变量的事实也final排除了任何后续对 static 的赋值,这些赋值会否定happens-before

您只需要声明executing好像volatile某些东西可以在初始化后为其分配一个新值。如果不进行一些令人讨厌的反思,这是不可能的。(并且 JLS 指出,如果你做那种事情来改变 a final,内存模型保证不适用。)


executing如果isfinal只是一个实例字段而不是一个字段,您将获得类似的效果static。推理略有不同,但在 JLS 中也明确提及。


最后,Java 语法不允许您组合volatilefinal修饰符。这种组合没有意义。

于 2020-06-21T09:40:35.657 回答
2

我们不能使用下面的代码

private static volatile final AtomicBoolean executing = new AtomicBoolean(false);

volatile 和 final 一起使用是无效的。正如@RealSkeptic 所说,永远不会改变(最终)的 var 不需要 volatile。Volatile 用于那些值在运行时被一个或多个线程更改的变量。

//快乐学习

于 2020-06-21T09:40:19.050 回答