代码之家  ›  专栏  ›  技术社区  ›  yegor256

“不一致同步”是什么意思?

  •  7
  • yegor256  · 技术社区  · 14 年前

    这是我的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 回复  |  直到 14 年前
        1
  •  18
  •   brain    14 年前

    因为你只有在设置 names 变量,而不是当你读它的时候。因此,在读和写之间,另一个线程可以执行,您可以创建两个arraylist并用数据填充它们,第一个创建的线程将得到GC'ed。

    您需要将synchronized块放在读和写周围,或者将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
             }
           }
         }
      }
    
        2
  •  7
  •   Nikita Rybak    14 年前

    你第一次提到 names 里面 scan 不属于 synchronized 封锁。
    E、 g.,如果 扫描 从两个不同的线程调用两次 姓名 是空的,可能是这样的

    1. if (names == null) 从第一个线程被处理(到 true ).
    2. if(名称==空) 从第二个线程被处理(到 真的 ).
    3. 第一个线程进入 同步的 区块,分配 姓名 然后离开 同步的 封锁。
    4. 第二个线程进入 同步的 区块,分配 姓名 然后离开 同步的 封锁。

    现在, 姓名 初始化两次。这只是一种可能的情况,你会得到意想不到的结果。