【问题标题】:Is volatile needed, in case of only synchronized access [duplicate]在仅同步访问的情况下需要 volatile [重复]
【发布时间】:2015-10-06 15:53:11
【问题描述】:

emitting 变量应该是 volatile 吗? emit() 方法是从不同的线程调用的,emit 必须是可见的。
但它只能在synchronized 块中访问。 // ... 是完成工作的地方,但此处未引用 emitting

那么,如果synchronized 的结构是固定的,我还需要volatile 来代替emitting 吗? (为什么?)

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;
            }
        }
        // ...
    }

弗兰克

【问题讨论】:

    标签: java concurrency


    【解决方案1】:

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

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

    来自Java concurrency in practice一书:

    为了安全地发布一个对象,同时引用 对象和对象的状态必须对其他人可见 同时线程。正确构造的对象可以通过以下方式安全发布:

    • 从静态初始化器初始化对象引用;
    • 将对其的引用存储到易失性字段或原子引用中 ;
    • 将对它的引用存储到正确构造的对象的最终字段中;
    • 将对它的引用存储到由锁正确保护的字段中

    注意: 被锁保护表示进入同步块

    【讨论】:

    • 感谢您的回答,如果您能回答,只是一个问题。如果在 Object1 上创建了同步块,并且在 Object1 上的该同步块中访问了另一个 Object2 的状态,它仍然安全吗?
    • @nits.kk 在没有从同步块外部修改 Object2 状态之前,它是安全的。或者它是从与 Object1 不同的变量上的同步块修改的
    • 感谢@Davide Lorenzo 的澄清...
    猜你喜欢
    • 1970-01-01
    • 2018-09-25
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 2014-03-20
    • 2015-07-01
    相关资源
    最近更新 更多