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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM