JUC学习系列十一(并发类容器)

2023-10-26

首先了解一下并发类容器和同步类容器的概念,以及这两类的区别:

一、同步类容器

同步类容器都是线程安全的,但在某些场景下可能需要加锁来保护复合操作。复合类操作如:迭代(反复访问元素,遍历完容器中的所有元素)、跳转(根据指定的顺序找到当前元素的下一个元素)、以及条件运算。这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为,最经典的便是ConcurrentModificationException,原因是当容器迭代的过程中,被并发的修改了内容,这是由于早期迭代器设计的时候并没有考虑并发修改的问题。

同步类容器:如古老的Vector/HashTable。这些容器的同步功能其实都是有JDK的Collections.syncronized等工厂方法区创建实现的。其底层的机制无非就是用传统的synchronized关键字对每个公用的方法都进行同步,使得每次只能有一个线程访问容器的状态。这很明显不满足我们今天互联网时代高并发的需求,在保证线程安全的同时,也必须有足够好的性能。

二、并发类容器

jdk5.0以后提供了多种并发类容器来替代同步类从而改善性能。同步内容器的状态都是串行化的,他的虽然是线程安全,当时降低了并发性。在多线程环境的时候,严重降低了应用程序的吞吐量。

并发类容器则是针对并发而设计的,使用了ConcurrentHashMap代替给予散列的传统的HashTable,而且,ConncurrentHashMap中,添加了一些常见复核操作的支持,以及使用了CopyOnWriteArrayList代替Voctory,并发的CopyOnWriteArraySet,以及并发的Queue,ConcurrentLinkedQueue和LinkedBlockingQueue,前者是高性能的队列,后者是以阻塞形式的队列,具体实现Queue还有很多,例如ArrayBlockingQueue、PriorityBlockingQueue、SynchrousQueue等等

三、同步类容器分析:

同样的Hashtable也是在HashMap的基础上加入了synchronized关键字,来实现线程安全性。

 

 JDK的Collections.syncronized等工厂方法,实现的线程安全,只是把方法上的锁,改变为了new一个对象锁。但是本质上和vector和Hashtable的性能差不多。

 用法实例:

public class CollectionsTest {

    public static void main(String[] args) {
        List<String> list=new ArrayList<>();
        //这样safeList就是线程安全的list了
        List<String> safeList= Collections.synchronizedList(list);

        Map<String,Object> map=new HashMap<>();
        Map<String,Object> safeMap=Collections.synchronizedMap(map);

        //其实HashSet的源码是利用HashMap的key这部分实现的
        Set<String> set=new HashSet<>();
        Set<String> safeSet=Collections.synchronizedSet(set);
    }

}

 原理剖析:

 Collections内部类,对传进来的Collection子类进行了一次包装,这个内部类使用的就是new 一个对象锁的方式,实现线程安全性的,不在是在方法上加锁了。


 

 四、并发类容器分析

CopyOnWriteArrayList,底层使用到了重入锁,在写的时候加锁,在读的时候不加锁。写的时候复制一份要操作的数组,之后再设置回去。而这个数组用volatile保证内存可见性。

CopyOnWriteArraySet底层使用的是CopyOnWriteArrayList实现的,add()调用的是list里面的addIfAbsent(E e)保证去重。其他的也基本上都是调用list里面的方法。

 ConcurrentHashMap这个类的原理是,内部使用了一个Node链表形式的内部类,在put的时候根据一定规则,给一定范围的Node加锁,即减小的锁的粒度,来提高并发访问时的性能。这个类的源码有6000+行,内部类有20多个,很多操作是使用的CAS操作。

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JUC学习系列十一(并发类容器) 的相关文章

  • Java并发编程实战——并发容器之ThreadLocal及其内存泄漏问题

    文章目录 ThreadLocal的简介 ThreadLocal的实现原理 ThreadLocalMap详解 ThreadLocal内存泄漏问题 ThreadLocal的使用场景 ThreadLocal的简介 之前写过用ThreadLocal
  • 并发编程系列之Fork/Join

    前言 上节我们讲了阻塞队列 Java中的并发容器就算有了个基本的认识 今天我们来介绍一种线程工作模式 叫Fork Join 他是JDK7之后提供的一个并行执行框架 主要的思想我觉得是分而治之 将一个大的任务分成多个小的任务并行执行 然后等所
  • 并发编程集合

    转载自郑金维老师 一 synchronized 一 原子性 有序性 可见性 1 1 原子性 数据库的事务 ACID A 原子性 事务是一个最小的执行的单位 一次事务的多次操作要么都成功 要么都失败 并发编程的原子性 一个或多个指令在CPU执
  • Java 线程池ExecutorService 等待队列问题

    本人博客原地址 Java 线程池ExecutorService 等待队列问题 创作时间 2019 09 30 11 12 35 1 首先看下Executor获取线程池 这样方式 可以设置线程池的大小 但是了解线程池的内部原理的情况下 这样的
  • Java中的Semaphore信号量机制

    目录 什么是信号量机制 Semaphore工作流程 Semaphore使用方式 什么是信号量机制 信号量机制是一种通过使用计数器来控制共享资源访问的机制 计数器计数的是共享资源的访问许可 如果计数器大于0则允许访问 如果为0 则拒绝访问 J
  • 【多线程】三种实现方案

    目录 1 多线程中的并发和并行概念 2 多线程中的进程和线程概念 3 多线程的实现方案 3 1 方式1 继承Thread类的方式进行实现 3 2 方式2 实现Runnable接口 3 3 方式3 Callble和Future 可以获取返回结
  • Java并发编程:Copy-On-Write机制详解

    前言 在多线程并发访问共享数据时 可能会出现并发问题导致程序崩溃 数据异常等情况 为了避免这些问题 Java中提供了多种并发控制方法 其中Copy On Write COW 机制就是一种常用的技术 本文将详细介绍COW机制的概念 如何保证线
  • 多线程-Thread类的常用方法及使用场景

    众所周知 操作线程就必须熟读线程的API方法 万一你开个多线程刹不住车就歇菜了 下面就介绍一些API基本用法 包括sleep join yield interrupt sleep 让当前线程睡一会 原生用法Thread sleep 毫秒 会
  • 场景题之最快返回结果

    场景题之最快返回结果 问题描述 输入中文 最快从百度翻译 谷歌翻译 有道翻译获取结果返回 代码实现 思路 采用CompletableFuture实现 多个CompletableFuture可以串行执行 也可以并行执行 其中anyOf 方法只
  • 生产者与消费者问题?

    生产者消费者模式是并发 多线程编程中经典的设计模式 简单来看 就是一个类负责生产 一个类负责消费 举例来说 一个变量 生产者不断增加这个变量 消费者不断减少这个变量 在互联网应用中 抢票机制就是应用了该模式 比如大麦网演唱会门票抢票 123
  • 并发编程系列之volatile内存语义

    前言 前面介绍顺序一致性模型时 我们提到了程序如果正确的同步就会具备顺序一致性 这里所说的同步泛指广义上的同步 其中包括就包括同步原语volatile 那么volatile声明的变量为什么就能保证同步呢 这又是如何实现的呢 今天就让我们一起
  • 【并发】并发

    并发 进程和线程 进程 资源分配的基本单位 可以理解为在内存中运行的程序 每个进程都有独立的内存空间 一个进程包含多个线程 线程 任务执行的基本单位 负责进程中任务的执行 每个线程共享进程的内存空间 一个线程使用时 其他线程必须等待 用户
  • Callable接口详解

    Callable接口详解 Callable 返回结果并且可能抛出异常的任务 优点 可以获得任务执行返回值 通过与Future的结合 可以实现利用Future来跟踪异步计算的结果 Runnable和Callable的区别 1 Callable
  • C/C++基于线程的并发编程(二):线程安全和线程锁

    线程安全 所谓线程安全不是指线程的安全 而是指内存的安全 线程是由进程所承载 所有线程均可访问进程的上下文 意味着所有线程均可访问在进程中的内存空间 这也是线程之间造成问题的潜在原因 当多个线程读取同一片内存空间 变量 对象等 时 不会引起
  • 在Windows下使用MingGW[GCC+OpenMP]和CodeBlocks开发多核应用基本环境配置

    转自 http blog csdn net danny xcz article details 3332251 从06年开始 多核开发已经越来越多的成为所有应用设计必须考虑的问题 我使用MingGW CodeBlocks来测试OpenMP多
  • Java 中的Lock锁对象(ReentrantLock/ReentrantReadWriteLock)详解

    目录 1 Lock Objects 详解 2 Java 中的 Lock Objects 的实现原理 3 ReentrantLock 详解 4 ReentrantReadWriteLock 详解 5 Lock锁的等待和唤醒 6 Lock 和
  • 测试开发工程师面试总结(一)——Java基础篇

    本文面向对象 测试开发工程师 服务端自动化方向 随手百度一下都能找到 岗位面试总结 但是有关测开岗位的面试总结却寥寥无几 总体原因可能是这两个 1 测试行业整体水平参差不齐 导致不同公司面试的问题不能抽象出来写概览 2 很多做测开的人可能内
  • synchronized的作用和用法

    郁闷 参考 synchronized的作用和用法 Java中Synchronized的使用 文章目录 简单介绍 用法 实战实例 修饰代码块 修饰普通方法 修饰静态方法 简单介绍 synchronized关键字是用来控制线程同步的 就是在多线
  • JUC编程

    1 JUC JUC就是java util concurrent工具包的简称 这是一个处理线程的工具包 JDK 1 5开始出现的 1 传统的synchronized public class Synchronized public stati
  • Java线程(Thread)生命周期的6种状态

    当线程被创建并启动以后 它既不是一启动就进入了执行状态 也不是一直处于执行状态 在线程的生命周期中 可能处于不同的状态 java lang Thread State 列举出了这6种线程状态 线程状态 导致状态发生条件 New 新建 线程刚被

随机推荐

  • elm分类器功能_一文带你读懂线性分类器

    本文为 AI 研习社编译的技术博客 原标题 Linear Classifier 作者 Thomas Pernet 翻译 邓普斯 杰弗 涂世文 Disillusion 校对 邓普斯 杰弗 审核 酱番梨 整理 菠萝妹 原文链接 https me
  • 前端h5 播放器vue-video-player

    1 安装依赖 npm install vue video player 2 在main js全局引入 import VideoPlayer from vue video player import video js dist video j
  • 计蒜客 - 44280 UnDetected(并查集).md

    题目大意 题目链接 给你n个圆 ans 为 最少 前多少个 圆 能把x轴 0 200 完全覆盖 完全覆盖是相交的圆 的最左端 lt 0 最右端 gt 200 输出ans 1 分析 并查集维护边界和输入的圆是否相交 代码 1 2 3 4 5
  • 【大数据】Doris:基于 MPP 架构的高性能实时分析型数据库

    Doris 基于 MPP 架构的高性能实时分析型数据库 1 Doris 介绍 Apache Doris 是一个基于 MPP Massively Parallel Processing 大规模并行处理 架构的高性能 实时的分析型数据库 以极速
  • java上传实现 spring boot +element ui

    先从element ui el upload组件开始介绍
  • linux虚拟机ifconfig command not found

    在linux虚拟机中输入ifconfig命令 出现ifconfig command not found 以下是排查过程 1 cd sbin然后ls 没找到ifconfig命令 2 想通过yum install net tools安装 发现出
  • linux基础——linux线程间通信及同步机制总结

    线程间的通信有两种情况 1 一个进程中的线程与另外一个进程中的线程通信 由于两个线程只能访问自己所属进程的地址空间和资源 故等同于进程间的通信 2 同一个进程中的两个线程进行通信 本文说的就是第二种情况 关于进程间通信 IPC 可以看我的另
  • 测试理论----软件测试四大测试过程

    原文链接 1 测试分析 1 要点 1 软件需求分析 2 测试需求项的提取 3 用户使用场景分析 4 测试工具的调研和选取 5 测试缺陷分析 2 分工 1 测试人员 提取测试点 输出需求跟踪矩阵 2 测试负责人 输出测试计划 2 测试设计 1
  • i.mx287学习笔记6-声卡驱动

    上面是我的微信和QQ群 欢迎新朋友的加入 1 查看声卡设备 aplay l 可以看到存在一个声卡设备 2 制作一个音频文件 我是先下载一个音频 然后使用audition裁剪一下 转化为wav再进行播放的 转换出来之后 3 测试
  • 输入若干个整数,以-1标记输入结束,输出其中的最大数

    题目描述 输入若干个整数 以 1标记输入结束 输出其中的最大数 输入 若干个整数 以 1标记输入结束 输出 其中的最大数 样例输入 1 2 5 7 8 6 1 6 1 样例输出 8 1 使用数组 这种方法可以进行求解 但是如果输入的是 1的
  • 712. 两个字符串的最小ASCII删除和 -- 动规

    712 两个字符串的最小ASCII删除和 class MinimumDeleteSum 712 两个字符串的最小ASCII删除和 https leetcode cn problems minimum ascii delete sum for
  • Spring中的AOP和事务管理,以及SpringBoot中使用事务

    一 什么是事务 狭义上的事务特指数据库事务 一方面 当多个程序并发访问数据库时 事务可以在这些应用程序之间提供一个隔离方法 以防止彼此的操作互相干扰 另一方面 事务为数据库操作提供了一个从失败中恢复到正常状态的方法 同时提供了数据库即使在异
  • 全国等级保护测评机构推荐目录

    转自 http www djbh net webdev web LevelTestOrgAction do p nlbdLv3 id 402885cb35d11a540135d168e41e000c 国家信息安全等级保护工作协调小组办公室推
  • 机器学习实战:AdaBoost预测病马率

    import numpy as np 函数说明 加载数据集 Parameters filename 文件名 Returns dataMat 数据集 labelMat 标签 def loadDataSet filename numFeat l
  • select epool

    一 问题引出 联系区别 问题的引出 当需要读两个以上的I O的时候 如果使用阻塞式的I O 那么可能长时间的阻塞在一个描述符上面 另外的描述符虽然有数据但是不能读出来 这样实时性不能满足要求 大概的解决方案有以下几种 1 使用多进程或者多线
  • Deepin 20.1 安装nvidia显卡驱动 爬坑

    前言 之前用的是ubuntu系统 装得也是双系统 然后最近看到了deepin 系统 然后就装了下 在装nvidia显卡时 遇到了重启蓝屏的问题 在反复重装N多次系统同时查阅N多次网友资料时 总结出以下几点 当然如果你想安装的话直接滑下方 不
  • 【计算机视觉

    文章目录 一 检测相关 8篇 1 1 Attending Generalizability in Course of Deep Fake Detection by Exploring Multi task Learning 1 2 Harv
  • 基于参数shared_pool_reserved_size进一步理解共享池shared pool原理

    结论 1 与共享池相关的参数为 shared pool size shared pool reserved size shared pool reserved pct shared pool reserved min alloc 2 sha
  • String的三种遍历方式

    include include using namespace std int main string s1 string s2 hello bite string s3 s2 1 for循环 for size t i 0 i lt s2
  • JUC学习系列十一(并发类容器)

    首先了解一下并发类容器和同步类容器的概念 以及这两类的区别 一 同步类容器 同步类容器都是线程安全的 但在某些场景下可能需要加锁来保护复合操作 复合类操作如 迭代 反复访问元素 遍历完容器中的所有元素 跳转 根据指定的顺序找到当前元素的下一