【数据类型】Collections.synchronizedMap 多线程Map,与HashMap的不同

一、Collections.synchronizedMap 简介

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 实现原理,关键源码

1、基础原理

Collections.synchronizedMap 是通过返回一个线程安全的 Map 包装器来实现的,它在对 Map 进行修改操作时会使用同步块来确保线程安全。该方法的基本原理如下:

  • 封装原始 Map: synchronizedMap 方法接受一个 Map 对象作为参数,然后返回一个线程安全的封装器。封装器会保持对原始 Map 的引用。
  • 同步块: 在对 Map 进行修改的方法(例如put、remove等)中,使用同步块(synchronized)来确保同一时刻只有一个线程可以执行这些修改操作。

2、实现源码

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();}
        }

        // ... 其他方法也都使用同步块来确保线程安全

        // ...
    }
}

在上述代码中,SynchronizedMapCollections.synchronizedMap 返回的封装器类。它实现了 Map 接口,同时包含了一个内部封装的原始 Map 对象 m,以及一个共享的锁对象 mutex

3、关键原理和实现逻辑:

  • 同步块: 在 SynchronizedMap 的实现中,所有可能引起修改的方法都使用 synchronized (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的区别

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值