2017-07-18 12 views
-1

我们需要同步这里private static Map对象如果多个线程使用getObject方法,先用给定的密钥检查上map值,如果没有找到,然后把新的对象使用该密钥对map对象。如果多个线程使用公共方法读取特定键的值,我们是否需要在一个私有静态Map对象上进行同步?

private static Map<String, Object> map = new HashMap<>(); 

public Object getObject(String key){ 
    Object obj = map.get(key); 
    if(obj == null){ 
     obj = new Object(); 
     map.put(key, obj); 
    } 
    return obj; 
} 

回答

1

你不做只读。 您也将值放入地图中,并且HashMap不适用于并发线程(如果其中至少有一个线程在地图上进行了某些操作)。

所有这一切都应该是同步的,以避免线程之间的竞争条件:

Object obj = map.get(key); 
if(obj == null){ 
    obj = new Object(); 
    map.put(key, obj); 
} 

的竞争条件实施例:

对于没有包含在映射中的键"a",一个线程可能被暂停在这里:

if(obj == null){ 

另一个线程可以用钥匙"a"执行代码等都提出ŧ他在地图中的元素,因为它还没有被包含。
当第一个线程恢复时,它将覆盖密钥"a"的地图内容。

请注意,如果您使用ConcurrentHashMap,则可以使用putIfAbsent()确保以原子方式执行操作(检查并放置,如果不退出)。

+0

感谢您的回答,我有一个关于putIfAbsent()的问题,在这里我们需要传递一个新创建的对象,这是不好的,我想创建对象只有当它在地图中丢失。 –

+1

'map.computeIfAbsent(key,k - > new Object())'。 –

+0

谢谢这会帮助我。 –

2

它说,它right there in the Javadoc

请注意,此实现不是同步的。如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则它必须在外部同步。 (结构上的修改是指添加或删除一个或多个映射的操作;仅改变与该一个实例已经包含一个键相关联的值不被结构上的修改。)

你打电话put如果该值是空(或不存在),所以你正在进行结构修改。如果您从多个线程调用此方法,则需要同步。

相关问题