同步嵌套映射和集 (Java)
我在地图内的地图内有一个嵌套集,我试图在两个线程上同步。
映射是这样实例化的:
private final Map<Manageable, Map<String, Set<Manageable>>> manageableMap =
Collections.synchronizedMap(new HashMap<Manageable, Map<String, Set<Manageable>>>());
这是我用来向映射添加值的函数:
private void put(Manageable key, Manageable value, String valueType) {
synchronized (manageableMap) {
Map<String, Set<Manageable>> setMap = manageableMap.get(key);
if (setMap == null) {
setMap = new HashMap<String, Set<Manageable>>();
manageableMap.put(key, Collections.synchronizedMap(setMap));
}
synchronized (setMap) {
Set<Manageable> set = setMap.get(valueType);
if (set == null) {
set = new HashSet<Manageable>();
setMap.put(valueType, Collections.synchronizedSet(set));
}
synchronized (set) {
set.add(value);
}
}
}
}
Intellij IDEA 警告我正在同步局部变量 setMap 和 set。
我对同步相当陌生,我想知道这是否是正确的方法 像这样同步嵌套数据结构。
谢谢你的帮助。
I have a nested set within a map within a map that I am trying to synchronize over two threads.
The map is instantiated as such:
private final Map<Manageable, Map<String, Set<Manageable>>> manageableMap =
Collections.synchronizedMap(new HashMap<Manageable, Map<String, Set<Manageable>>>());
This is the function I use to add values to the map:
private void put(Manageable key, Manageable value, String valueType) {
synchronized (manageableMap) {
Map<String, Set<Manageable>> setMap = manageableMap.get(key);
if (setMap == null) {
setMap = new HashMap<String, Set<Manageable>>();
manageableMap.put(key, Collections.synchronizedMap(setMap));
}
synchronized (setMap) {
Set<Manageable> set = setMap.get(valueType);
if (set == null) {
set = new HashSet<Manageable>();
setMap.put(valueType, Collections.synchronizedSet(set));
}
synchronized (set) {
set.add(value);
}
}
}
}
Intellij IDEA warns me that I am synchronizing on local variables setMap and set.
I am fairly new to synchronization and I was wondering if this is the proper way to
synchronize a nested data structure like this.
Thank you for you help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你只需要在manageableMap上进行同步即可。一次只有1个线程可以获取manageableMap上的锁,因此如果一个线程已经获取了manageableMap上的锁,则不需要进一步锁定set和setMap,因为只有1个线程(锁定manageableMap的线程)可以访问set和setMap 。
You only need to synchronize on manageableMap. Only 1 thread at a time can acquire the lock on manageableMap, so if a thread has acquired the lock on manageableMap, further locking on set and setMap is not needed, since only 1 thread (the thread that locked manageableMap) can access set and setMap.
同步适用于特定的对象实例,而不适用于持有对它们的引用的字段或变量,因此您必须确保同步发生在相同的对象实例上,无论它们是否仅由局部变量引用。
在这种特殊情况下,IDEA 无法静态检查代码是否执行您想要的操作,警告只是某种“代码气味”,警告您效果可能不符合预期。
最好的办法是通过注销正在同步的实例来测试代码,并检查它们是否是您期望的实例 - IDEA 还具有在调试期间标记对象实例的选项,以检查您同步的对象是否相同或不同的实例。
synchronization works on particular object instances, not on the fields or variables holding references to them, so you must make sure that the sunchronization occurs on the same object instances, no matter whether they are refenced by local variables only.
In that particular case IDEA cannot statically check whether the code does what you want, the warning is just some kind of 'code smell' warning you that the effect might not be as expected.
Best bet is you test your code by logging out the instances that you are synchronizing on and check whether they are the ones you expect - IDEA has also the Option to mark object instances during debugging to check whether the objects you synchronize on are the same or different instances.
如果您始终手动控制同步,您可能不需要使用 Collections.synchronizedMap。目标地图上同步的一个部分就可以了。
If you always control the synchronization manually you probably don't need to use Collections.synchronizedMap. One section synchronized on the target map will do.