变量的同步和本地副本

发布于 2024-08-09 16:30:14 字数 463 浏览 10 评论 0 原文

我正在查看一些具有以下习惯用法的遗留代码:

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (myMap) {
    item = myMap.get(myKey);
}

我从 Intelli-J 的代码检查中得到的警告是:

Synchronization on local variable 'myMap'

这是适当的同步吗?为什么?

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (someGlobalInstance.getMap()) {
    item = myMap.get(myKey);
}

I'm looking at some legacy code which has the following idiom:

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (myMap) {
    item = myMap.get(myKey);
}

The warning I get from Intelli-J's code inspections is:

Synchronization on local variable 'myMap'

Is this the appropriate synchronization and why?

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (someGlobalInstance.getMap()) {
    item = myMap.get(myKey);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

握住我的手 2024-08-16 16:30:14

这被标记为问题的原因是因为同步局部变量通常是一个坏主意。

如果someGlobalInstance.getMap()返回的对象始终相同,那么同步块实际上使用了准全局对象监视器,并且代码产生了预期的结果。

如果您只需要同步 get()/put() 调用并且没有任何更大的同步块,我也同意使用同步包装器的建议。但请确保地图通过包装器访问,否则您将有另一个出现错误的机会。

另请注意,如果 someGlobalInstance.getMap() 确实始终返回同一对象,那么即使您的第二个代码示例也无法正常工作,甚至可能比您的原始代码,因为您可以在与调用 get() 的对象不同的对象上进行同步。

The reason this is flagged as a problem is because synchronizing on local variables is usually a bad idea.

If the object returned by someGlobalInstance.getMap() is always the same, then the synchronized block does in fact use that quasi-global objects monitor and the code produces the expected result.

I also agree with the suggestion to use a synchronized wrapper, if you only need to synchronize the get()/put() calls and don't have any bigger synchronized blocks. But make sure that the Map is only accessed via the wrapper or you'll have another chance for bugs.

Also note that if someGlobalInstance.getMap() does not return the same object all the time, then even your second code example will not work correctly, it could even be worse than your original code since you could synchronize on a different object than the one you call get() on.

孤单情人 2024-08-16 16:30:14

我认为代码可能是合理的,具体取决于 getMap() 方法的作用。如果它保留对必须在线程之间共享的实例的引用,那就有意义了。该警告无关紧要,因为局部变量未在本地初始化。

I think the code could be sound, depending on what the getMap() method does. If it keeps a reference to an instance that has to be shared between threads it makes sense. The warning is irrelevant since the local variable is not initialized locally.

oО清风挽发oО 2024-08-16 16:30:14

我认为最好使用 地图的同步包装

I think it would be better to use synchronized wrapper for your map

一直在等你来 2024-08-16 16:30:14

Alex 是正确的,通过调用 Collections.synchronizedMap(Map) 添加同步包装器是这里的典型方法。但是,如果您采用这种方法,在某些情况下您可能仍然需要同步 Map 的锁;例如,当迭代地图时。

Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());

// Synchronized on map to prevent ConcurrentModificationException whilst iterating.
synchronized (syncMap) {
  for (Map.Entry<String, String> entry : syncMap.entrySet()) {
    // Do work
  }
}

在您的示例中,来自 IDEA 的警告可以被忽略,因为很明显您的局部变量: map 是从其他地方 (someGlobalInstance) 检索的,而不是在方法内创建的,因此可以从其他线程访问。

Alex is correct in that adding a synchronized wrapper by calling Collections.synchronizedMap(Map) is a typical approach here. However, if you take this approach there may still be situations where you need to synchronized on the Map's lock; e.g. when iterating over the map.

Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());

// Synchronized on map to prevent ConcurrentModificationException whilst iterating.
synchronized (syncMap) {
  for (Map.Entry<String, String> entry : syncMap.entrySet()) {
    // Do work
  }
}

In your example, the warning from IDEA can be ignored, as it's evident that your local variable: map is retrieved from somewhere else (someGlobalInstance) rather than being created within the method, and can therefore potentially be accessed from other threads.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文