簡體   English   中英

客戶端鎖定

[英]Client-side locking

以下是 JCIP 的摘錄

在此處輸入圖片說明

作者說為了使上面的代碼線程安全,我們必須使用客戶端鎖定。

為了使這種方法起作用,我們必須通過使用客戶端鎖定或外部鎖定來使用與 List 相同的鎖定。 客戶端鎖定需要保護使用某個對象 X 的客戶端代碼,並且 X 使用鎖來保護它自己的狀態。 為了使用客戶端鎖定,您必須知道 X 使用什么鎖。

在此處輸入圖片說明

為什么我們不能一開始就簡單地將List< E >對象設為私有以使 ListHelper 類成為線程安全的?

ListHelper每個實例都包含自己的列表的情況下,您可以將該列表ListHelper私有,然后在ListHelper實例上進行同步。 我想這是一個有點構造的例子,用盡可能少的代碼來說明這一點。 IMO 名稱ListHelper意味着我可以傳遞一個外部列表,該列表顯然可以被多個ListHelper實例重用。

我想說的重點是:給定代碼,並且不改變list可見性(可能會破壞其他代碼),您比當前的ListHelper實例更好地在list同步。

首先,我們應該了解作者的目的。 作者的目的是構建一個線程安全的List工具,它對包括putifAbsent方法在內的所有方法都是安全的。

ListHelper也可能有如下其他一些方法:

public void addList(E x)
{
     list.add(x);
}
public void removeList(E x)
{
     list.remove(x);
}

如果某個線程調用removeList並且第二個線程調用addList而第三個線程調用putIfAbsent,那么,因為它們是不同的鎖,所以會發生錯誤。

這里的重點是表明如果您使用同步列表,並且您想添加另一個線程安全的方法,您必須使用相同的鎖。 這里的目的是表明,如果您在輔助類中對此進行同步,但依賴列表提供的同步上的其他方法(鎖定列表實例 - 它會破壞線程安全。

是的,我們可以簡單地首先將 List< E > 對象設為私有,以使 ListHelper 類成為線程安全的。 這樣,List<E> 對象就不需要是線程安全的。

class ImprovedList<T> {
    private final List<T> list;

    public ImprovedList(List<T> list) {
        this.list = list;
    }

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

如果我們將列表設為私有,那么除了 put-if-absent 之外,您將如何利用列表的其他操作? 然后,您還必須實現列表的所有其他操作,因此要實現所有列表操作,您將使用 List 實現 ListHelper。 現在,您正在默默地走向組合模式 由於您使用 List 接口實現了 ListHelper,所以現在它不再是 Helper 類,它變成了列表本身,因此我們可以說它是一個改進列表

class ImprovedList<T> {
    private final List<T> list;

    public ImprovedList(List<T> list) {
        this.list = list;
    }

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM