是否有必要使用Java的Collections
数据结构的专用并发版本(例如CopyOnWriteArrayList vs ArrayList),如果对一对数据结构的所有访问始终都包含在获取和释放锁定中(特别是,对数据结构的任何修改使用静态同步方法)。例如:
public static synchronized Item doIt() {
// remove something from data structure 1
// add the removed item to data structure 2
// return removed item
}
我知道synchronized方法一次只执行一个线程执行更新,但是当一个线程退出该方法时,其他线程是否保证看到更新的数据结构,或者我是否还需要专门的并发该担保的数据结构?
修改:
这是我尝试做的更好的例子:
private static final List<Item> A;
private static final HashMap<Integer,Item> B;
public static Item doSomething() {
// some stuff ...
Item item = doIt();
// some other stuff ...
return item;
}
private static synchronized Item doIt() {
Item theItem = A.remove( A.size()-1 );
B.put( theItem.getId(), theItem );
return theItem;
}
答案 0 :(得分:6)
是,如果访问始终包装在同步的方法/块中。
这是因为,synchronized在同步的方法/块(在同一个对象上)之间建立了发生之前的关系。引自Synchronized Methods in the Java Tutorial:
其次,当同步方法退出时,它会自动建立 与任何后续调用a之前发生的关系 同一对象的同步方法。这种保证会发生变化 到对象的状态对所有线程可见。
然而,真正将所有访问权限包装在同步块中非常重要。例如,如果您愿意从像这样的同步方法返回对列表的引用
public synchronized List<Object> GetList() {
return this.myList;
}
并使用synchronized方法之外的列表,您将无法获得该保证!
答案 1 :(得分:2)
同步不仅仅是相互排斥。也就是说,它是关于块内(并且在它之前)的所有动作的可见性与随后获取相同锁的任何其他线程。
因此,当您对结构的所有访问使用锁定时,不需要并发数据结构。
最后,只是为了确保:您必须使用锁定来进行所有访问,包括所有读取。