java - 在仅同步访问的情况下是否需要 volatile

标签 java concurrency

<分区>

emitting 变量应该是可变的吗? emit() 方法从不同的线程调用,并且 emit 必须是可见的。
但它只能在 synchronized block 中访问。 //... 是完成工作的地方,但是这里没有引用 emitting

那么,如果synchronized 的结构是固定的,我还需要一个volatileemitting 吗? (为什么?)

static final class C {
    boolean emitting = false; // shall be volatile ?

    public void emit() {
        synchronized (this) {
            if (emitting) {
                return;
            }
            // ...
            emitting = true;
        }

        // ...

        synchronized (this) {
            if (!condition()) {
                emitting = false;
                return;
            }
        }
        // ...
    }

弗兰克

最佳答案

如果仅从synchronized block 访问它,则不需要volatile 关键字。

Synchronized 保证在同步块(synchronized block)内访问的变量的更改对于进入同步块(synchronized block)的所有线程都是可见的。

摘自 Java 并发实践一书:

To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:

  • Initializing an object reference from a static initializer;
  • Storing a reference to it into a volatile field or Atomic Reference ;
  • Storing a reference to it into a final field of a properly constructed object;
  • Storing a reference to it into a field that is properly guarded by a lock.

注意: 被锁保护意味着进入同步块(synchronized block)

关于java - 在仅同步访问的情况下是否需要 volatile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32974336/

相关文章:

java - 修改 jar 中的文件

javascript - history.back() 之后的代码会发生什么?

git - git实现并发的加锁策略?

go - 具有并发支持的golang哈希表

java - 通过网络推送 JAX-B 对象

java - 嵌套哈希表?

mysql - 如何正确使用事务和锁来保证数据库的完整性?

Java序列化导致并发修改异常

java - GC 在堆内存使用完 99% 后运行

java - 从 if block 返回 Java