这是来自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的节点中删除节点,则节点变为无效。这里有问题吗?
答案 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中的了。从地图中删除它不会修改节点。