客户端锁定

时间:2015-09-18 11:40:47

标签: java multithreading

以下摘录自JCIP

enter image description here

作者说,为了使上面的代码是线程安全的,我们必须使用客户端锁定。

  

要使此方法有效,我们必须使用List使用的相同锁,方法是使用客户端锁定或外部锁定。客户端锁定需要保护使用某个对象X的客户端代码,其中锁X用于保护自己的状态。为了使用客户端锁定,您必须知道X使用什么锁。

enter image description here

为什么我们不能简单地制作 List< E> 首先将对象设为私有,以使ListHelper类具有线程安全性?

4 个答案:

答案 0 :(得分:6)

ListHelper的每个实例都包含自己的列表的情况下,您可以将该列表设为私有,并在ListHelper实例上进行同步。我想这是一个有点构造的例子,用尽可能少的代码来表达观点。 IMO名称ListHelper意味着我可以传递一个外部列表,该列表可以被多个ListHelper实例清楚地重用。

我要说的是:给定代码不会改变list的可见性(可能会破坏其他代码),您最好在list上比当前ListHelper同步实例

答案 1 :(得分:0)

首先,我们应该了解作者的目的。作者的目的是构建一个线程安全的List工具,它对包括putifAbsent方法在内的所有方法都是安全的。

ListHelper也可能有以下其他方法:

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

如果某个线程调用removeList,第二个线程调用addList,第三个线程调用putIfAbsent, 然后,因为它们是不同的锁,所以会发生错误。

答案 2 :(得分:0)

这里要说明的是,如果使用同步列表,并且想要添加另一个线程安全方法,则必须使用相同的锁。这里的目的是为了表明如果你在helper类中同步,但依赖于列表提供的同步上的其他方法(锁定列表实例 - 它将破坏线程安全。

答案 3 :(得分:0)

是的,我们可以简单地将List 对象首先私有化,以使ListHelper类成为线程安全的。这样,List 对象不必是线程安全的。

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