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