Collections.synchronizedMap 是 Java 中提供的工具方法,用于创建一个同步(线程安全)的 Map。它接受一个现有的 Map 对象,并返回一个通过同步包装后的 Map。
下面是一个简单的示例:
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SynchronizedMapExample {
public static void main(String[] args) {
// 创建一个普通的 HashMap
Map<String, Integer> hashMap = new HashMap<>();
// 使用 Collections.synchronizedMap 方法创建同步的 Map
Map<String, Integer> synchronizedMap = Collections.synchronizedMap(hashMap);
// 现在 synchronizedMap 就是一个线程安全的 Map 对象
// 同步块示例
synchronized (synchronizedMap) {
// 在同步块中对 synchronizedMap 进行操作
}
}
}
Collections.synchronizedMap 是通过返回一个线程安全的 Map 包装器来实现的,它在对 Map 进行修改操作时会使用同步块来确保线程安全。该方法的基本原理如下:
synchronizedMap
方法接受一个 Map 对象作为参数,然后返回一个线程安全的封装器。封装器会保持对原始 Map 的引用。synchronized
)来确保同一时刻只有一个线程可以执行这些修改操作。Collections.synchronizedMap
的关键源码如下:
public class Collections {
// ...
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
return new SynchronizedMap<>(m);
}
static class SynchronizedMap<K,V> implements Map<K,V>, Serializable {
// ...
// 内部封装的原始 Map 对象
private final Map<K,V> m;
// ...
public V put(K key, V value) {
// 同步块确保线程安全
synchronized (mutex) {return m.put(key, value);}
}
public void clear() {
// 同步块确保线程安全
synchronized (mutex) {m.clear();}
}
// ... 其他方法也都使用同步块来确保线程安全
// ...
}
}
在上述代码中,SynchronizedMap
是 Collections.synchronizedMap
返回的封装器类。它实现了 Map 接口,同时包含了一个内部封装的原始 Map 对象 m
,以及一个共享的锁对象 mutex
。
SynchronizedMap
通过持有一个原始 Map 对象 m
的引用,将修改操作委托给这个原始 Map 对象。通过这种方式,SynchronizedMap 实际上是对原始 Map 对象的一种包装。mutex
是一个共享的锁对象,用于控制同步块的访问。这个锁对象的作用是确保在同一时刻只有一个线程可以执行关键代码块,从而保证了对 Map 的操作是线程安全的。这是一种简单粗暴但有效的方式,被称为悲观锁,因为它悲观地认为在并发环境中会有冲突,因此通过加锁来保护共享资源。在 Collections.synchronizedMap 中,mutex
的选择是 Collections.synchronizedMap 对象本身。在 Collections.synchronizedMap 中,
mutex
的选择是 Collections.synchronizedMap 对象本身,这是因为 Java 中的synchronized
关键字是与对象关联的。当一个线程进入同步块时,它要获取的是这个对象的锁。因此,为了实现同步,需要使用一个对象作为锁。
Collections.synchronizedMap
是一个工具类,用于返回线程安全的 Map 对象。当你调用Collections.synchronizedMap(map)
时,实际上是返回了一个包装后的 SynchronizedMap 对象,该对象持有了一个内部的原始 map 对象,并使用 synchronized 来确保对原始 map 的操作是线程安全的。为了保证线程安全,SynchronizedMap 内部使用了一个 mutex 对象,而这个 mutex 对象就是Collections.synchronizedMap
对象本身。这种选择是为了确保在对原始 map 进行操作时,所有需要同步的线程都是以同一个锁对象为基础的,这样才能够有效地实现线程安全。
总的来说,mutex 的选择是为了将 SynchronizedMap 包装后的对象作为一个整体来加锁,确保对原始 map
的修改操作是原子的,从而实现线程安全。
需要注意的是,虽然 Collections.synchronizedMap
提供了线程安全的访问,但在高并发环境下,使用这种方式可能导致性能瓶颈。因为同步是在整个 Map 对象上进行的,当多个线程同时访问时,只有一个线程能够执行修改操作,其他线程必须等待。
在Java 5及之后的版本,推荐使用 ConcurrentHashMap
来获得更好的并发性能。 ConcurrentHashMap
在设计上采用了分段锁(Segment)的机制,允许多个线程同时修改不同的段,从而提高了并发性能。详情参考【数据类型】ConcurrentHashMap分段锁实现高并发;与HashMap的区别