java - Java 中的双重检查锁定问题

标签 java multithreading synchronization thread-safety

<分区>

其中一篇文章提到了 “Double Check Locking” 的问题。请看下面的例子

public class MyBrokenFactory {
  private static MyBrokenFactory instance;
  private int field1, field2 ...

  public static MyBrokenFactory getFactory() {
    // This is incorrect: don't do it!
    if (instance == null) {
      synchronized (MyBrokenFactory.class) {
        if (instance == null)
          instance = new MyBrokenFactory();
      }
    }
    return instance;
  }

  private MyBrokenFactory() {
    field1 = ...
    field2 = ...
  }
}

原因:-(请注意编号的执行顺序)

Thread 1: 'gets in first' and starts creating instance.

1. Is instance null? Yes.
2. Synchronize on class.
3. Memory is allocated for instance.
4. Pointer to memory saved into instance.

[[Thread 2]]

7. Values for field1 and field2 are written
to memory allocated for object.

.....................
Thread 2: gets in just as Thread 1 has written the object reference
to memory, but before it has written all the fields.

5. Is instance null? No.
6. instance is non-null, but field1 and field2 haven't yet been set!
   This thread sees invalid values for field1 and field2!

问题:
由于新实例(new MyBrokenFactory())的创建是从synchronized block 中完成的,在整个初始化完成之前(private MyBrokenFactory()完全执行)是否会释放锁?

引用 - https://www.javamex.com/tutorials/double_checked_locking.shtml

请解释。

最佳答案

问题出在这里:

Thread 2: gets in just as Thread 1 has written the object reference to memory, but before it has written all the fields.

Is instance null? No.

没有同步,线程 2 可能 instance 视为null,即使线程 1 已经写入了它。请注意,instance 的第一次检查是在 synchronized block 之外:

if (instance == null) {
  synchronized (MyBrokenFactory.class) {

由于第一次检查是在 block 外完成的,因此无法保证线程 2 会看到 instance 的正确值。

我不知道你想用 field1field2 做什么,你甚至都没有写过它们。

回复。您的编辑:

As the creation of the new instance(new MyBrokenFactory()) is done from the synchronized block

我认为您要问的是两个实例字段 field1field2 是否保证可见。答案是否定的,问题与 instance 相同。因为您不从同步块(synchronized block)中读取 instance,所以无法保证这些实例字段将被正确读取。如果 instance 不为空,则永远不会进入 synchronized block ,因此不会发生同步。

关于java - Java 中的双重检查锁定问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53077255/

相关文章:

Java wait() 不抛出 InterruptedException

java - 是否有一个类似 ORM 的 java 库,带有运行时定义的表来构建 sql 查询?

java - 寻找适用于 scala、java 或 python 的通用 Oauth 库

java - 选择多行

Java bean 验证带范围的大写字母

java - 如果当前线程崩溃,读写锁会发生什么

c# - 以原子方式从 ConcurrentQueue 中获取所有内容

c - 如何创建一个新线程以使 pcap_loop() 和 gtk_main() 兼容?

java - 如何使异步调用同步

c++ - 在 C++ 中处理中断