【问题标题】:How do I synchronize this properly?如何正确同步?
【发布时间】:2012-01-21 23:32:07
【问题描述】:
public void consumeResponse(OmwListResponse<T> response) {
    synchronized (response.getResultList()) { // XXX this isn't synchronized safely
        for (T t : response.getResultList()) {
            if (!cacheList.contains(t)) {
                cacheList.add(t);
            }
        }
    }
}

情况是我不希望任何人在此方法完成之前有机会 response.getResultList()cacheList。我该如何正确地做到这一点?

【问题讨论】:

  • 如果 getResultList() 在每次调用时都返回一个新列表,则 synchronized 块不会做任何有用的事情。
  • 只是一个参考getter。

标签: android multithreading synchronize


【解决方案1】:

创建一个锁对象:

private static final void LOCK = new Object();

然后同步。

【讨论】:

  • 是的,但是这个方法外部的东西还能改变 response.getResultList() 吗?或者 LOCK 甚至会锁定同步块中的所有内容,直到它完成?
  • @musselwhizzle - 同步块只会通过协作代码(即,在同一个锁对象上同步的代码)防止同时访问。如有必要,您可以将您的LOCK 对象设为public 并给它一个更有意义的名称(例如,OMW_RESPONSE_LOCK)。然后在锁定对象上与修改responsecacheList 的所有代码同步。我建议不要使用嵌套同步块,因为这是死锁的主要来源。
  • 嗯...我不确定我真的想走那条路。我希望我的同步从实现中隐藏起来。在这一点上,我更有可能制作 getResultList 的副本,然后运行我的循环。是的,我试图避免嵌套同步块。
  • @musselwhizzle - 这仍然不能保护您在制作副本时免受 resultList 的同时修改。没有好的办法:当一个或多个线程修改它时,所有访问resultList 的代码都需要同步。
  • 该死,所以标准的 Java 同步方法是创建公共属性并在其上进行同步?这听起来很糟糕,而且容易出错。为什么在这种情况下嵌套的同步块会不好?附言感谢所有的帮助。你摇滚,伙计!!!
【解决方案2】:

同步 cacheList 很容易。只需将使用它的代码包装起来:

synchronized(cacheList) {
   // Make changes to cacheList here
}

如果 cacheList 是公共成员并且您担心外部类会更改它,请将其设为私有成员并同步 getter 和 setter。这是唯一的方法,因为您无法控制其他类的操作,并且您有责任同步您的成员。

至于响应,这比较棘手,因为我不知道 OmwListResponse 是什么。你拥有那个班级吗?如果是这样,请使用与上述相同的方法。如果没有,你可能会倒霉。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 2016-10-31
    • 2023-03-17
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多