简体   繁体   English

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

[英]Groovy(/Java): Lock on unique values of a variable?

I have some code in a groovy script where if a graph for a certain name does not exist, I create a new instance of it. 我在一个groovy脚本中有一些代码,如果某个名称的图形不存在,我会创建一个新的实例。

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

The problem is this is running in parallel and the createGraph() call takes ~60 seconds, so sometimes I'll create 2 instances of the graph and only save 1 of them to my map (because they'll both see the map doesn't contain the name and then create it). 问题是这是并行运行并且createGraph()调用需要大约60秒,所以有时候我会创建2个图形实例,并且只将其中一个保存到我的地图中(因为它们都会看到地图没有' t包含名称,然后创建它)。 It's my understanding that I can lock on the map to avoid this problem, like so: 我的理解是我可以锁定地图以避免这个问题,如下所示:

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

But the problem with this is that creating a graph can take a while, and I want to be able to create graphs for several different names at the same time. 但问题是创建图形可能需要一段时间,我希望能够同时为多个不同的名称创建图形。 That is to say, if I get 3 concurrent requests to create graphs for foo , foo , and bar , I want to create foo and bar concurrently but not create the 2nd foo . 也就是说,如果我得到3个并发请求来为foofoobar创建图形,我想同时创建foobar但不创建第二个foo Is it possible for me to synchronize not on the map, but instead on specific name values? 我可以不在地图上同步,而是在特定的名称值上进行同步吗?

A quick solution is to: 快速解决方案是:

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

If you have two String s with the same contents but in different String objects, synchronized won't work properly, as it will synchronize on different objects and neither will block the other. 如果你有两个String s的内容相同,但在不同的String对象, synchronized将无法正常工作,因为它会在不同的对象同步,也不会阻止其他。

However, when intern() is given a String with certain contents, it always returns the same object every time for those contents, so synchronizing on that object will work properly. 但是,当intern()被赋予一个具有特定内容的String时,它总是每次为这些内容返回相同的对象,因此在对象上进行同步将正常工作。

This allows you to block only on the contents of that particular graphName rather than the whole graphMap , allowing more concurrency. 这允许您仅阻止特定graphName的内容而不是整个graphMap ,从而允许更多的并发性。 It also prevents any wasted work of adding a value for that key twice. 它还可以防止任何浪费的工作,即为该键添加两次值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM