【问题标题】:Will all java threads see shared resource updates after modification in synchronized method?在同步方法中修改后所有java线程都会看到共享资源更新吗?
【发布时间】:2014-08-05 15:22:29
【问题描述】:

如果对一对数据结构的所有访问总是与锁的获取和释放(特别是使用对数据结构进行任何修改的静态同步方法)。例如:

public static synchronized Item doIt() {
    // remove something from data structure 1
    // add the removed item to data structure 2
    // return removed item
}

我知道同步方法一次只会强制一个线程执行更新,但是当一个线程退出该方法时,其他线程是否可以保证看到更新的数据结构,还是我仍然需要专门的并发该保证的数据结构?

编辑:

这是我正在尝试做的一个更好的例子:

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

【问题讨论】:

  • 您不应该需要这样的集合,因为您正在手动执行锁定。但为什么要重新发明轮子呢?
  • @LuiggiMendoza 因为你不能在没有锁定的情况下原子地修改两个集合。
  • @WilliamF.Jameson 但是集合框架的这些并发版本已经具有这种锁定处理并允许对它们进行原子操作。再说一遍:为什么要重新发明轮子?
  • @LuiggiMendoza OP 有两个系列。这两个更新作为一个整体不会是原子的。
  • 您是否总是从同一类中的staticsynchronized 方法访问它们?仅当您始终在同一个对象上同步时,同步才会有所帮助。你知道 static synchronized 方法在哪个对象上同步吗?

标签: java concurrency


【解决方案1】:

,如果访问总是包装在同步方法/块中。

这是因为,synchronized 在同步方法/块(在同一个对象上)之间建立了 happens-before 关系。引用Synchronized Methods in the Java Tutorial:

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

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

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

并在同步方法之外使用列表,您将无法获得该保证!

【讨论】:

  • @RTF 现在我想知道为什么要将它们都设为static。看起来您遇到的是设计问题,而不是多线程问题。
【解决方案2】:

同步不仅仅是互斥。也就是说,它是关于在块内(以及在它之前)对随后获得相同锁的任何其他线程进行的所有操作的可见性

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-21
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多