内在vs互斥锁

时间:2014-09-30 13:50:37

标签: java synchronization

查看Collection's SynchronizedList的实现,我认识到内部列表上的所有访问都是通过锁定包装器的最终成员" mutex"来同步的。由于所有访问都在同一个对象上同步,为什么我们不要省略额外的互斥对象并只在列表本身上同步?是否只是因为其他人可以在该列表上同步并且我们可能会遇到死锁? 我问,因为我考虑实现一个容器类,它包含两个列表。 容器提供例如.addToL1(...)和.addToL2(...)。在这种情况下,内部列表是不可访问的,因此它应该足以在列表上本地同步,正确吗?

2 个答案:

答案 0 :(得分:2)

最强大的解决方案是锁定调用者无法访问的对象。 (我们暂时忽略反射和不安全)JDK开发人员必须考虑开发人员可以对库做的最糟糕的事情,因为有人会这样做以及他们无法想到的事情。

然而,如果您知道谁将使用它并了解其局限性,有时简单性是最重要的驱动因素。

答案 1 :(得分:2)

在这种情况下,它是专门完成的,因为从列表创建的子列表必须在父对象上同步

 public List<E> subList(int fromIndex, int toIndex) {
        synchronized(mutex) {
            return new SynchronizedList<E>(list.subList(fromIndex, toIndex),
                                        mutex);
        }
    }

如果按Collections.synchronizedList( list );创建同步列表,则会将互斥锁设置为this(即同步列表对象本身)。

但您也可以使用两个参数调用Collections.synchronizedList(),其中第二个参数将用作互斥锁。

一般而言,在公开可见的对象上进行同步并不是一个好主意,我更喜欢始终使用2参数版本并从代码的客户端隐藏互斥对象。