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

yeg*_*256 7 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
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Findbugs说:

Inconsistent synchronization of com.XXX.Foo.names; locked 40% of time
Run Code Online (Sandbox Code Playgroud)

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

bra*_*ain 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
         }
       }
     }
  }
Run Code Online (Sandbox Code Playgroud)


Nik*_*bak 7

第一次引用names内部scan是在synchronized块之外.
例如,如果scan从两个不同的线程调用两次并且names为null,则它可能是这样的

  1. if (names == null)从第一个线程处理(到true).
  2. if (names == null)从第二个线程处理(到true).
  3. 第一个线程进入synchronized块,分配names和离开synchronized块.
  4. 第二个线程进入synchronized块,分配names和离开synchronized块.

现在,names初始化两次.这只是一种可能出现意外结果的可能情况.