Groovy(/ Java):锁定变量的唯一值?

时间:2017-03-07 02:16:34

标签: java groovy

我在一个groovy脚本中有一些代码,如果某个名称的图形不存在,我会创建一个新的实例。

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

问题是它并行运行并且createGraph()调用大约需要60秒,所以有时候我会创建2个图形实例,并且只将其中一个保存到我的地图中(因为它们都会看到map不包含名称然后创建它)。我的理解是我可以锁定地图以避免这个问题,如下所示:

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

但问题是创建图表可能需要一段时间,我希望能够同时为多个不同的名称创建图表。也就是说,如果我有3个并发请求为 foo foo bar 创建图表,我想创建 foo bar 同时但不会创建第二个 foo 。我可以不在地图上同步,而是在特定的名称值上同步吗?

1 个答案:

答案 0 :(得分:3)

快速解决方案是:

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

如果您有两个String具有相同内容但位于不同String个对象中,synchronized无法正常工作,因为它会在不同对象上同步,也不会阻止另一个。

但是,当intern()String提供某些内容时,它每次都会为这些内容返回相同的对象,因此在 对象上进行同步将正常工作

这允许您仅阻止特定graphName的内容而不是整个graphMap的内容,从而允许更多的并发性。它还可以防止任何浪费的工作,即为该键添加两次值。