Java在局部变量图上同步

时间:2017-03-11 09:30:16

标签: java multithreading synchronized

这是来自apache zookeeper,类DataTree

的方法源代码
 /**
 * update the count of this stat datanode
 *
 * @param lastPrefix
 *            the path of the node that is quotaed.
 * @param diff
 *            the diff to be added to the count
 */
public void updateCount(String lastPrefix, int diff) {
    String statNode = Quotas.statPath(lastPrefix);
    DataNode node = nodes.get(statNode);
    StatsTrack updatedStat = null;
    if (node == null) {
        // should not happen
        LOG.error("Missing count node for stat " + statNode);
        return;
    }
    synchronized (node) {
        updatedStat = new StatsTrack(new String(node.data));
        updatedStat.setCount(updatedStat.getCount() + diff);
        node.data = updatedStat.toString().getBytes();
    }
    // now check if the counts match the quota
    String quotaNode = Quotas.quotaPath(lastPrefix);
    node = nodes.get(quotaNode);
    StatsTrack thisStats = null;
    if (node == null) {
        // should not happen
        LOG.error("Missing count node for quota " + quotaNode);
        return;
    }

...

我的问题是为什么它在节点对象上同步?如果其他线程从作为HashMap的节点中删除节点,则节点变为无效。这里有问题吗?

2 个答案:

答案 0 :(得分:1)

  

我的问题是为什么它在节点对象上同步?

file_id = models.OneToOneField(A, on_delete = models.PROTECT) 充当同步对象。线程在一个对象上进行同步是很常见的,该对象的内部状态可以被其中一些线程修改。此同步强制线程之间的顺序。因此避免了竞争条件。您的代码没有显示它,但项目的其他部分可能会被其他线程修改node的内容。因此,node上同步的所有线程都将保持一致。

  

如果其他线程从HashMap节点中删除节点,则节点变为无效。这里有问题吗?

如果从散列映射中删除node,则并不意味着该节点无效。它不会被垃圾收集器破坏,因为它在您显示的代码中被引用。

只有在整个程序中不再引用时,

node才会无效。

答案 1 :(得分:1)

  

我的问题是为什么它在节点对象上同步?

似乎在本地同步时很奇怪,但请注意本地值来自函数外部(nodes,可能是实例成员)。因此,它同步的对象将可用于多个线程,显然该方法中的代码需要确保它不会在同一node的多个线程上并发运行。

在这种情况下,显然它正在保护node.data的更新,并且有充分的理由:它正在使用node.data,修改该数据,然后使用结果更新node.data。同时执行此操作的两个线程可能会踩到彼此的工作。

  

如果其他线程从HashMap节点中删除节点,则节点变为无效。

不,它不再是HashMap中的了。从地图中删除它不会修改节点。