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

这篇具有很好参考价值的文章主要介绍了【数据类型】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的区别文章来源地址https://www.toymoban.com/news/detail-802049.html

到了这里,关于【数据类型】Collections.synchronizedMap 多线程Map,与HashMap的不同的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Map集合体系(HashMap,LinkedHashMap,TreeMap)

    目录 1.Map集合 2.hashMap集合 3.LinkedHashMap集合 4. TreeMap集合 1.Map集合         Map集合是键值对集合         格式:{key1=value1, key2=value2, key3=value3, ...}         Map系列集合的特点都是由键决定的,值只是一个附属品,值不做要求 2.实现类有哪些?,各自有什么特点?  

    2024年02月21日
    浏览(41)
  • go数据类型-map

    go的map在面试时候经常会被问到。 最近看到群里有个被问到为什么map的每个桶中只装8个元素? 注:解决hash冲突还有一些别的方案:开放地址法 (往目标地址后面放)、再哈希法(再次hash) 跟进看 buckets的结构: 每个桶 定义了 有8个哈希值的容量。 这里就解释了为什么一个

    2024年02月05日
    浏览(36)
  • JavaSE进阶 | Map集合、HashMap集合、TreeMap集合

    目录 🏀Map集合概述  🥅Map接口常用的方法 🥅哈希表(散列表)数据结构 🥅同时重写HashCode和equals 🥅HashMap和Hashtable的区别 🥅Properties类 🥅TreeSet(TreeMap)集合 🥅自平衡二叉树数据结构 🥅实现比较器接口 🥅集合工具类Collections (1) Map和Collection没有继承关系,是一个平级的

    2023年04月09日
    浏览(44)
  • 【JavaScript】JS——Map数据类型

    存储键值对的对象。 能够记住键的原始插入顺序 任何值(对象或原始值)都可以作为键或值。 Map中的一个键 只能出现一次 ,新的值会覆盖旧的值。 迭代方式:for…of循环,返回一个 [key,value] 的数组。 键的相等:基于零值相等比较 Map与Object的比较 Map默认不包含任何键。

    2024年02月04日
    浏览(49)
  • go数据类型-sync.map

    在runtime的sync.map包中有定义: 整体的结构就如上图。 sync.map中有两个map 都是通过指针的形式 ,指向同一份value,但是key两个map都有各自存储。 看究竟是如何解决map并发的问题的。 正常读写走 m,就是read那个通过泛型结构体指向的那个 map,通过m这个map进行查找后,读取或者

    2024年02月05日
    浏览(41)
  • 第12章_集合框架(Collection接口,Iterator接口,List,Set,Map,Collections工具类)

    1.1 生活中的容器 1.2 数组的特点与弊端 一方面,面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。 另一方面,使用数组存储对象方面具有 一些弊端 ,而Java 集合就像一种容器,可以 动态地 把多个对象的引用放入容器中。 数

    2024年01月25日
    浏览(45)
  • HashMap学习和线程安全的HashMap

    HashMap的底层数据结构? HashMap在JDK1.8里面的Node数组加链表加红黑树,当链表长度大于8且数组长度大于64,链表转化为红黑树。当红黑树节点数小于6,红黑树转化为链表。在JDK1.7中是数组加链表。 为什么要用红黑树? 当hash冲突严重导致链表长度过长,影响查找性能。红黑树

    2024年01月20日
    浏览(33)
  • MyBatis 查询 MySQL 实现返回 List<Map> 或 Map 类型数据操作

      MyBatis 查询 MySQL 数据库,返回结果可以是具体的类、Map、ListMap 等等。将查询结果返回 Map 类型的优点是,不需要为本次查询额外创建类。如果只查询某几个特定的列,且不想额外创建类的话,就可以将结果返回 Map 或 ListMap。   如果能明确查询结果只有一条记录时,返

    2023年04月09日
    浏览(85)
  • 前端如何传递Array、Map类型数据到后端

    针对前后端分离的项目,避免不了前端需要传递Array、Map类型的数据到后端,那么要怎么实现这种情况的参数传递呢?请看下文分说。 前端有Map类型数据如下: 将Map类型数据转化成String,再进行传递 将前端传过来的String数据,解析为JSON对象,再强制转为java的Map 以上。本文

    2024年02月02日
    浏览(68)
  • Golang教程一(环境搭建,变量,数据类型,数组切片map)

    目录 一、环境搭建 1.windows安装 2.linux安装  3.开发工具 二、变量定义与输入输出 1.变量定义 2.全局变量与局部变量 3.定义多个变量 4.常量定义 5.命名规范 6.输出 格式化输出 7.输入  三、基本数据类型 1.整数型 2.浮点型 3.字符型 4.字符串类型 转义字符 多行字符串 5.布尔类型

    2024年04月16日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包