在synchronized方法中修改后,所有java线程是否会看到共享资源更新?

时间:2014-08-05 15:22:29

标签: java concurrency

是否有必要使用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;
}

2 个答案:

答案 0 :(得分:6)

,如果访问始终包装在同步的方法/块中。

这是因为,synchronized在同步的方法/块(在同一个对象上)之间建立了发生之前的关系。引自Synchronized Methods in the Java Tutorial

  

其次,当同步方法退出时,它会自动建立   与任何后续调用a之前发生的关系   同一对象的同步方法。这种保证会发生变化   到对象的状态对所有线程可见

然而,真正将所有访问权限包装在同步块中非常重要。例如,如果您愿意从像这样的同步方法返回对列表的引用

public synchronized List<Object> GetList() {
    return this.myList;
}

并使用synchronized方法之外的列表,您将无法获得该保证!

答案 1 :(得分:2)

同步不仅仅是相互排斥。也就是说,它是关于块内(并且在它之前)的所有动作的可见性与随后获取相同锁的任何其他线程。

因此,当您对结构的所有访问使用锁定时,不需要并发数据结构。

最后,只是为了确保:您必须使用锁定来进行所有访问,包括所有读取。