• Collections.synchronizedList使用方法陷阱(1)


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

    @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;
            }
        }
    }

  • 相关阅读:
    第四章 虚拟机性能监控与故障处理工具
    C++_异常5-异常规范和栈解退
    C++_异常4-将对象用作异常类型
    C++_异常3-异常机制throw try catch
    C++_异常2-返回错误码
    C++_异常1-调用abort()
    C++_类继承7-类设计回顾
    C++_类继承6-继承和动态内存分配
    C++_类继承5-抽象基类
    C++_类继承4-访问控制protected
  • 原文地址:https://www.cnblogs.com/luojiabao/p/11309007.html
Copyright © 2020-2023  润新知