Java 在局部变量插图上同步

Java synchronized on local variable illustration

这是来自apache zookeeper的方法源码,classDataTree

 /**
 * 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 节点中删除节点,则节点无效。这里有什么问题吗?

My question is why it synchronized on the node object?

node 充当同步对象。线程在一个对象上同步是很常见的,该对象的内部状态可以被其中一些线程修改。这种同步强加了线程之间的顺序。因此避免了竞争条件。您的代码没有显示它,但项目的其他部分可能 node 的内容被其他线程修改。因此,所有在 node 上同步的线程将是一致的。

If other thread remove the node from nodes which is a HashMap, then node becomes invalid. Is there some problem here?

如果从hashmap中移除node,并不意味着该节点将无效。它也不会被垃圾收集器销毁,因为它在您显示的代码中被引用。

node只有在整个程序中不再引用时才会失效。

My question is why it synchronized on the node object?

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

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

If other thread remove the node from nodes which is a HashMap, then node becomes invalid.

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