解决方案 »

  1.   

    up up up up up up up 
      

  2.   

    synchronized修饰方法是获得本对象的锁,而不是list
    在boolean absent = !list.contains(x);和list.add(x);之间,list就有可能会被别的对象改变(比如通过反射),导致线程不安全
    用synchronized(list)的话就不会了
      

  3.   

    从操作角度来看,用了Collections.synchronizedList,不会出现数据错误,数组越界之类从逻辑绝度来看,下面的也不见得安全,用list做锁,其他没synchronized(list)的代码块可以直接操作list
    而contains 和 add两个动作中间有间隙,其他操作非synchronized(list)可以从中间插入
    假设类中其他代码块操作list的时候都有synchronized(list),可以认为是安全的
    但同样道理,类中其他操作list的方法全部用synchronized修饰其实也很安全
      

  4.   

    Collections操作集合的对象,源代码中也是将对象(要进行加锁)的对象都设置为final的,一般都这样.一般不会把普通的对象进行lock,要么就用类字节码对象lock.
      

  5.   

    我给你解释下吧。
    首先的你的List已经是线程安全的了(public List<E> list = Collections.synchronizedList(new ArrayList<E>());具体可参见API),但是你写了个方法实现无重复添加的功能,上面的方法,对方法加synchronized,假如已经执行到 if 行了,别的地方调用了add,这时boolean absent = !list.contains(x)的判断已经无效了,就出现你说的list不安全了。第二种给List加synchronized就OK,因为你在进入时,别的地方不能调用add
      

  6.   

    第一个获得ListHelper 对象的锁,这把锁和list对象明显是不同的锁。进入同步块后到退出前,其它的线程还能调用list.add(),list.remove()方法。
    但第二个例子,因为 synchronized(list),这时操作的是list对象的锁,也就是list.add(),list.contains()等方法用的是同一把锁,当进入同步块时,其它的线程不可能在同步块退出前调用list.add(),list.remove()等这些同步方法,所以是线程安全的。
      

  7.   


    看了下源码,发觉自己错了。
    SynchronizedList的锁就是自己本身,所以第二中的确是能锁住的