无意发现了这个例子,拿来记住

@NotThreadSafe
class BadListHelper <E> {
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());

    public synchronized boolean putIfAbsent(E x) {
        boolean absent = !list.contains(x);
        if (absent)
            list.add(x);
        return absent;
    }
}

虽然说putIfAbsent方法加了synchronized的锁关键字,但是这个putIfAbsent方法获得锁和list对象的获得锁不是同一个锁;

putIfAbsent获得锁是BadListHelper这个类的锁对象,

list获得锁对象是list;

如果这么写,那list依旧能够被其他线程获取锁对象来改变list对象的值,就会导致数据出错,或者两两线程在访问这个方法的时候拿到的list数据可能会有错误;所以这么写是不对的;

要想保证list数据不出错,就要给他自己上锁,其他线程将不能获得list锁来来改变list对象。

@ThreadSafe
class GoodListHelper <E> {
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    public boolean putIfAbsent(E x) {
        synchronized (list) {  //获得list锁对象,其他线程将不能获得list锁来来改变list对象。
            boolean absent = !list.contains(x);
            if (absent)
                list.add(x);
            return absent;
        }
    }
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-23
  • 2021-11-12
  • 2022-12-23
  • 2022-12-23
  • 2022-01-15
  • 2021-08-08
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-11-27
  • 2021-07-11
  • 2022-03-08
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案