为什么内部锁定对象不需要特殊处理(静态、最终、易失)



在这个内部锁的预言机示例中,监视器对象从未被声明为易失性,最终或与任何其他常规对象没有任何区别

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++;
        }
    }
}
有很多

问题在争论易失性块与同步块

  • 易失场和同步块,
  • Java 中易失性和同步性之间的区别
  • 何时在 Java 的多线程中使用易失性与同步,
  • 您是否曾经在 Java 中使用过 volatile 关键字

和不可变对象

  • 什么是不可变对象,
  • Java 中的不变性和同步
  • 不可变对象 Java Concurreny)在多线程中。

作为旁注,我理解声明对象 final与不变性为什么可以修改最终对象以及为什么将锁定对象声明为 final 不会使其不可变之间的微妙区别。

但是,我们有著名的单例类延迟初始化模式,其中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;
    }
}

在上面的代码示例中,它使用 Class 对象作为锁。

既然对于由多个线程访问的对象,您需要使用上述某种机制来确保原子访问,为什么对于固有锁对象不需要任何特殊处理?

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

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

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

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

C.f. 安全出版

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

它可能应该是最终的。 但是 final 并不是什么特别的东西——它只在一种特殊情况下需要(将函数内声明的变量引用到匿名类中)。 任何其他情况 final只是提醒程序员不要覆盖变量 - 您可以在程序中删除单词final的所有其他使用,它将完美运行。 你是对的,程序员可以分配给它,然后引起问题。 但如果他不这样做,那就没有问题了。 因此,在创建 final 时继续使用 final,但程序不需要编译。

至于静态 - 取决于用例。 是要监视类的所有实例,还是独立监视每个实例? 在第一种情况下,您在第二种情况下不使用静态。

不需要易失性,因为多个线程实际上并未更改对象。 它正在同步。 这是完全不同的,并且Java语言的旧部分比易失性更旧。 没有必要使变量易失性,因为您不会更改它,并且用于监视对象的内部数据结构已经知道它们需要线程安全(并且以比易失性承诺更强大的方式)。

在这个内部锁的预言机示例中,监视器对象从未声明为易失性、最终对象或与任何其他常规对象没有任何区别。

那不是真的。见下文。

既然对于由多个线程访问的对象,您需要使用上述某种机制来确保原子访问,为什么对于固有锁对象不需要任何特殊处理?

它确实有特殊待遇。它是同步的。

最新更新