java - 为什么内在锁对象不需要特殊处理(static、final、volatile)?

标签 java multithreading synchronization immutability volatile

在此oracle example内部锁等等,监视器对象从未被声明为 volatile、final 或与任何其他常规对象没有任何区别

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}

有很多问题争论 volatile block 与同步块(synchronized block)

和不可变对象(immutable对象)

作为旁注,我理解声明对象为最终对象与不变性之间的细微差别 why-can-final-object-be-modified以及为什么将锁对象声明为final不会使其不可变。

但是,我们有著名的模式 singleton class惰性初始化,其中使用 volatile 变量是必不可少的。

public class SingletonDemo {
    private static volatile SingletonDemo instance;
    private SingletonDemo() { }

    public static SingletonDemo getInstance() {
        if (instance == null ) {
            synchronized (SingletonDemo.class) {
                if (instance == null) {
                    instance = new SingletonDemo();
                }
            }
        }

        return instance;
    }
}

上面的code example使用 Class 对象作为锁。

既然对于多线程访问的对象需要使用上面的某种机制来保证原子访问,为什么对于内嵌锁对象不需要任何特殊处理呢?

最佳答案

这些锁不需要特殊处理,因为 MsLunch 对象本身需要先发布,然后才能被任何其他线程看到。

public class MyMain {
  public static void main(String... args) {
    MsLunch lunch = new MsLunch();
    // ...

这是线程安全的,因为局部变量(“lunch”)对于多个线程不可见。

接下来,下面的类使本地引用对系统中的所有线程可见。当这种情况发生时,我们需要使用 volatile volatile 关键字有效地创建了安全发布对象的内存屏障。这包括分配之前进行的所有写入,包括构造对象时内部进行的写入。

C.f. Safe Publication

public class MyMain {

  public static volatile MsLunch publicLunch;

  public static void main(String... args) {
    MsLunch lunch = new MsLunch();
    publicLunch = lunch;
    //...
  }
}

关于java - 为什么内在锁对象不需要特殊处理(static、final、volatile)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35686765/

相关文章:

.net - 学习实现线程池-使用autoresetevent时,信号事件丢失

java - 从 Socket 流读取 XML

java - GWT从2.7.0升级。 2.8.2(或2.8.1)不工作

java - AtomicReference 无法避免 java 多线程中的竞争条件

java - 此代码是否需要嵌套锁?

java - 线程同步问题(更新变量 sum)

java - "compose"在并发上下文中意味着什么?

java - 使用 Contains 方法过滤输入的多个不同行

java - 将 JScrollPane 添加到 JTextArea

java - 读取站点源: � characters