[英]Java synchronized on local variable illustration
这是来自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的节点中删除该节点,则该节点将变为无效。 这里有什么问题吗?
我的问题是为什么它在节点对象上同步?
node
充当同步对象。 线程在其内部状态可以被其中一些线程修改的对象上同步是很常见的。 该同步在线程之间强加了顺序。 因此避免了比赛条件。 您的代码没有显示它,但是项目的其他部分可能会由其他线程修改node
的内容。 结果,在node
上同步的所有线程将保持一致。
如果其他线程从作为HashMap的节点中删除该节点,则该节点将变为无效。 这里有什么问题吗?
如果将node
从哈希图中删除,则并不意味着该节点将无效。 它也不会被垃圾收集器破坏,因为它已在您显示的代码中引用。
仅当在整个程序中不再引用该node
时,该node
才是无效的。
我的问题是为什么它在节点对象上同步?
在本地上进行同步似乎很奇怪,但是请注意,本地的值来自函数外部( nodes
,它可能是实例成员)。 因此,正在同步的对象将可用于多个线程,并且显然该方法中的代码需要确保该对象不会在同一node
多个线程上并发运行。
在这种情况下,显然,它可以保护node.data
的更新,并且有充分的理由:它采用了node.data
,修改了该数据,然后使用结果更新了node.data
。 同时执行此操作的两个线程可能会占用彼此的工作。
如果其他线程从作为HashMap的节点中删除该节点,则该节点将变为无效。
不,它不再存在于HashMap中。 从地图中删除它不会修改节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.