什么“不一致的同步”意味着什么?

时间:2010-11-15 17:47:39

标签: java synchronization

这是我的Java 1.6类:

public class Foo {
  private ArrayList<String> names;
  public void scan() {
    if (names == null) {
      synchronized (this) {
        this.names = new ArrayList<String>();
        // fill the array with data
      }
    }
  }
}

Findbugs说:

Inconsistent synchronization of com.XXX.Foo.names; locked 40% of time

这是什么意思,我做错了什么?当两个或多个客户同时拨打Foo.scan()时,我正试图避免出现问题。

2 个答案:

答案 0 :(得分:18)

您只是在设置names变量时才进行同步而不是在阅读时进行同步。因此,在读取和写入之间,另一个线程可以执行,并且您将创建两个ArrayLists并用数据填充它们,第一个创建的将获得GC。

您需要将同步块放在读取和写入周围,或者将synchronized修饰符添加到方法中。

public class Foo {
  private ArrayList<String> names;
    public void scan() {
      synchronized (this)
        if (names == null) {
           this.names = new ArrayList<String>();
           // fill the array with data
         }
       }
     }
  }

答案 1 :(得分:7)

第一次在names内引用scan超出synchronized块。
例如,如果从两个不同的线程中调用scan两次并且names为空,则可能是这样的

    处理第一个帖子的
  1. if (names == null)(到true)。
  2. 来自第二个线程的
  3. if (names == null)被处理(到true)。
  4. 第一个主题进入synchronized块,分配names并离开synchronized阻止。
  5. 第二个帖子进入synchronized阻止,分配names并离开synchronized阻止。
  6. 现在,names被初始化两次。这只是一种可能导致意外结果的可能情况。