当前位置:网站首页>Basic concepts of concurrency, operations, containers
Basic concepts of concurrency, operations, containers
2022-08-10 09:00:00 【hard work boy】
文章目录
基本概念
并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这Several programs are running on the same processor,但任一个时刻点上只有一个程序在处理机上运行.
并发Concurrent和并行Parallel的区别
并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在A period of time when the threaded code runs,其它线程处于挂起状.这种方式我们称之为并发(Concurrent).
并行:当系统有一个以上CPU时,则线程的操作有可能非并发.当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel).
JDK提供的容器类
JDK 提供的这些容器大部分在 java.util.concurrent 包中.
ConcurrentHashMap: 线程安全的 HashMap
CopyOnWriteArrayList: 线程安全的 List,在读多写少的场合性能非常好,远远好于 Vector. ConcurrentLinkedQueue: 高效的并发队列,使用链表实现.可以看做一个线程安全的
LinkedList,这是一个非阻塞队列.
BlockingQueue: 这是一个接口,JDK 内部通过链表、数组等方式实现了这个接口.表示阻塞队
列,非常适合用于作为数据共享的通道.
ConcurrentSkipListMap: 跳表的实现.这是一个 Map,使用跳表的数据结构进行快速查找.
ConcurrentHashMap
HashMap 不是线程安全的,Available in concurrent scenariosCollections.synchronizedMap() 方法包装HashMap.But by using a global lock to synchronize concurrent access between different threads will bring non-negligible performance problems.HashMap 的线程安全版本ConcurrentHashMap 无论是读操作还是写操作都能保证很高的性能:在进行读操作时(几乎)不需要加锁,而在写操作时通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问.
CopyOnWriteArrayList
很多应用场景中,读操作可能会远远大于写操作.由于读操作根本不会修改原有的数据,因此对于每次读取都进行加锁其实是一种资源浪费.我们应该允许多个线程同时访问 List 的内部数据,毕竟读取操作是安全的.
CopyOnWriteArrayList 读取是完全不用加锁的,And writes don't block read operations either.只有写入和写入之间需要进行同步等待.这样一来,读操作的性能就会大幅度提升.
CopyOnWriteArrayList 类的所有可变操作(add,set 等等)都是通过创建底层数组的新副本来实现的.当 List Do not modify the original content when it needs to be modified,而是对原有数据进行一次复制,将修改的内容写入副本.写完之后,再将修改完的副本替换原来的数据,这样就可以保证写操作不会影响读操作了. CopyOnWrite 就是想要When a block of memory is modified, the write operation is not performed in the original memory block,而是将内存拷贝一份,在新的内存中进行写操作,写完之后呢,就将指向原来内存指针指向新的内存,原来的内存就可以被回收掉了.
CopyOnWriteArrayList 写入操作 add() 方法在添加集合的时候加了锁,保证了同步,避免了多线程写的时候会 copy 出多个副本出来.
阻塞队列BlockingQueue和非阻塞队列ConcurrentLinkedQueue
线程安全的 Queue 可以分为阻塞队列和非阻塞队列,A classic example of a blocking queue isBlockingQueue,非A classic example of a blocking queue is ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列. 阻塞队列可以通过加锁来实现,非阻塞队列可以通过 CAS 操作实现.
阻塞队列BlockingQueue
阻塞队列(BlockingQueue)被广泛使用在“生产者-消费者”问题中,提供了Blockable insertion and removal的方法.当队列容器已满,生产者线程会被阻塞,直到队列未满;当When the queue container is empty,消费者线程会被阻塞,直至队列非空时为止.BlockingQueue 是一个接口,继承自 Queue,所以其实现类也可以作为 Queue 的实现来使用,而Queue 又继承自 Collection 接口.
阻塞队列BlockingQueue的三个实现类
ArrayBlockingQueue
ArrayBlockingQueue 是 BlockingQueue 接口的有界队列实现类,底层采用数组来实现.ArrayBlockingQueue 一旦创建,容量不能改变.其Concurrency control is controlled using reentrant locks,不管是插入操作还是读取操作,都需要获取到锁才能进行操作.当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞.
ArrayBlockingQueue 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 ArrayBlockingQueue.而非公平性则是指访问ArrayBlockingQueue 的顺序不是遵守严格的时间顺序.如果保证公平性,通常会降低吞吐量.
LinkedBlockingQueue
LinkedBlockingQueue 底层基于单向链表实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用,The same is fair FIFO 的特性,与ArrayBlockingQueue 相比起来具有更高的吞吐量,为了防止LinkedBlockingQueue 容量迅速增,损耗大量内存.通常在创建LinkedBlockingQueue 对象时,会指定其大小,如果未指定,容量等于Integer.MAX_VALUE.
PriorityBlockingQueue
PriorityBlockingQueue 是一个支持优先级的无界阻塞队列.By default the element takes自然顺序进行排序,也可以通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数Comparator 来指定排序规则.PriorityBlockingQueue 并发控制采用的是 ReentrantLock,队列为无界队列(ArrayBlockingQueue是有界队列,LinkedBlockingQueue 也可以通过在构造函数中传入 capacity 指定队列最大的容量,但是PriorityBlockingQueue 只能指定初始的队列大小,后面插入元素的时候,如果空间不够的话会自动扩容).
简单地说,它就是 PriorityQueue 的线程安全版本.不可以插入 null 值,同时,插入队列的对象必须是可比较大小的(comparable),否则报ClassCastException 异常.它的插入操作 put 方法不会block,因为它是无界队列(take 方法在队列为空的时候会阻塞).
非阻塞队列ConcurrentLinkedQueue
ConcurrentLinkedQueue 这个队列使用链表作为其数据结构,It should be regarded as the queue with the best performance in high concurrency environment.它之所有能有很好的性能,是因为其内部复杂的实现.ConcurrentLinkedQueue 主要使用CAS Non-blocking algorithm to achieve thread safety,适合在对性能要求相对较高,同时对队列的读写存在多个线程同时进行的场景,即如果对队列加锁的成本较高则适合使用无锁的 ConcurrentLinkedQueue 来替代.
边栏推荐
猜你喜欢
J9 Number Theory: Macro Analysis of DAO Characteristics
凭借这份阿里架构师的万字面试手册,逆风翻盘,斩获阿里offer
【API 管理】什么是 API 管理,为什么它很重要?
DataStream API(基础篇) 完整使用 (第五章)
【OAuth2】十九、OpenID Connect 动态客户端注册
How to use [jmeter regular expression extractor] to solve the problem of returning the value as a parameter
【元宇宙欧米说】看UCOUCO如何将行为艺术融入元宇宙
【系统设计】S3 对象存储
TensorFlow 2.9的零零碎碎(一)
【微服务架构】为故障设计微服务架构
随机推荐
微信小程序--》小程序生命周期和WXS使用
【元宇宙欧米说】听兔迷兔如何从虚拟到现实创造潮玩新时代
不同的命令行风格
00后女孩月薪3200,3年买两套房,这个程序员变现新风口千万要把握住
【数据库架构】OLTP 和 OLAP:实际比较
How AliExpress sellers seize product search weight
初识Flink 完整使用 (第一章)
2 模块一:科研思维培养
【Unity入门计划】Collision2D类&Collider2D类
怎么使用【jmeter正则表达式提取器】解决返回值作参数的问题
幂次方(暑假每日一题 20)
【FAQ】【Push Kit】推送服务,回执配置一直报错、回执过期修改、怎么删除配置的回执
设计分享|基于单片机的从左到右流水灯
DeepFake换脸诈骗怎么破?让他侧个身
11111
JVM探究
【API架构】使用 JSON API 的好处
【系统设计】S3 对象存储
[OAuth2] Nineteen, OpenID Connect dynamic client registration
【企业架构】敏捷与企业架构:战略联盟