2017-03-07 33 views
1

我在groovy脚本中有一些代码,如果某个特定名称的图不存在,我创建一个新的实例。Groovy(/ Java):锁定变量的唯一值?

if (!graphMap.contains(graphName)) { 
    newGraph = createGraph(graphName) 
    graphMap.put(graphName, newGraph) 
} 

问题是这样的并行和createGraph()调用需要运行秒〜60秒,所以有时我会创建图表的两个实例,只保存它们的1到我的地图(因为他们”都会看到地图不包含名称,然后创建它)。这是我的理解是,我可以在地图上锁定来避免这个问题,像这样:

synchronized(graphMap) { 
    if (!graphMap.contains(graphName)) { 
    newGraph = createGraph(graphName) 
    graphMap.put(graphName, newGraph) 
    } 
} 

但这个问题是创建一个图形可能需要一段时间,我希望能够创建图表的几个不同的名字在同一时间。也就是说,如果我得到3个并发请求为FOOFOO,并酒吧创建图形,我想创建酒吧并发但不能创建第二FOO。我可以不在地图上同步,而是在特定的名称值上进行同步?

+1

解决此问题的一个方法是使用[双重检查锁定](https://en.wikipedia.org/wiki/Double-checked_locking),但是我不确定要为此锁定哪个对象。 – Powerlord

回答

3

一个快速的解决方案是:

graphName = graphName.intern(); 
synchronized(graphName) { 
    if (!graphMap.contains(graphName)) { 
    newGraph = createGraph(graphName) 
    graphMap.put(graphName, newGraph) 
    } 
} 

如果你有两个String s的相同的内容,但在不同的String对象,​​将不能正常工作,因为它会在不同的对象和没有同步会阻止对方。

然而,当intern()被赋予某些内容的String,它总是为那些内容每次都返回相同的对象,因此在同步该对象将正常工作。

这使您可以只对该特定graphName的内容进行阻止,而不是整个graphMap,从而实现更高的并发性。它还可以避免浪费两次为该密钥添加值的浪费工作。

+0

非常干净的解决方案。谢谢! – user7352005