并发编程(下)

发布时间:2024年01月21日

目录

七、对象结构

?编辑

八、synchronized锁实现

当synchronized修饰方法:

当synchronized修饰代码块:

九、AQS(AbstractQueuedSynchronizer)

十、ReentrantLock锁实现

十一、JUC常用类

一、ConcurrentHashMap

二、CopyOnWriteArrayList

三、CopyOnWriteArraySet

四、辅助类 CountDownLatch

十二、线程池

????????池:

? ? ? ? 优点:

线程池:

? ? ? ???ThreadPoolExecutor构造方法中的7个参数:


七、对象结构

????????在 Hotspot虚拟机中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充;Java对象头是实现 synchronized的锁对象的基础,一般而言,synchronized使用的锁对象是存储在 Java对象头里。它是轻量级锁和偏向锁的关键。

????????对象头中有一块区域称为Mark Word,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID等等。

八、synchronized锁实现

????????通过底层指令控制实现。

当synchronized修饰方法:

????????底层指令会添加ACC_SYNCHRONIZED。

????????进入方法时使用monitorenter检测,?执行完毕使用monitorexit释放锁。

当synchronized修饰代码块:

????????进入代码块时使用monitorenter检测,?执行完毕使用monitorexit释放锁。

九、AQS(AbstractQueuedSynchronizer)

????????AQS是一个用来构建锁和同步器的框架,使用 AQS能简单且高效地构造出同步器,是 JUC中

核心的组件。是一个底层具体的同步实现者,很多同步的类底层都用到了AQS。

? ? ? ??volatile int ?state; 用于标记有没有线程在访问共享资源。变量 state表示锁状态,0-锁未被使

用,大于 0锁已被使用共享变量 state,使用 volatile修饰保证线程可见性。

????????通过 getState方法获取锁状态,?compareAndSetState 方法使用 CAS机制设置状态。

十、ReentrantLock锁实现

????????ReentrantLock基于 AQS。

????????ReentrantLock是 java.util.concurrent.locks包下的类,在并发编程中它可以实现公平锁和非

公平锁实现同步,支持可重入。

????????ReentrantLock总共有三个内部类,并且三个内部类是紧密相关的。

十一、JUC常用类

?????Java 5.0在 java.utilconcurrent包中提供了多种并发容器类来改进同步容器的性能。

一、ConcurrentHashMap

? ? ? ? HashMap:键值对 双列集合,键不能重复,值可以重复。

? ? ? ? hashCode();equals();

? ? ? ? 结构:哈希表默认长度为16,数组在满75%时扩容至两倍。

? ? ? ? ? ? ? ? ? 链表>=8,并且哈希表长>=64。

? ? ? ? ? ? ? ? ? 红黑树。

? ? ? ? HashMap是单线程的,不安全

? ? ? ? HashTable是多线程的,给方法加了synchronized锁,线程安全。但读写共用一把锁,导致并发访问效率低,适用于并发访问量小的。

????????ConcurrentHashMap?是使用CAS+synchronized保证安全。

? ? ? ? put时先用key计算hash值,在计算位置。

? ? ? ? 如果,位置没有元素(null),采用CAS机制尝试放入,

????????如果,此位置存在元素,那么用第一个元素作为锁对象,使用synchronized加锁,这样会降低粒度,有多个方法进入put中操作提高并发效率。

? ? ? ? 如果,多个线程对同一个位置操作,那么必修一个一个操作。

注意:ConcurrentHashMap和 HashTable?不支持为null的键和值。因为,表达有歧义,无法分辨null是指没有找到key,还是指key的值为null。

二、CopyOnWriteArrayList

? ? ? ? ArrayList 单列集合,是数组实现的,可以存储重复元素,是有序的(添加顺序)

可以自动扩容,默认长度是10,默认扩容为1.5倍。是线程不安全的。

? ? ? ? Vector 与ArrayList区别是 线程安全的,扩容为2倍。加锁是在方法上加的,读写方法共享同一个锁,并发效率低。

? ? ? ? 添加修改方法会加锁,每次改变值时,会复制一个新数组,在新数组上修改,如果此时有读操作来,可以从原数组上读取,修改完成后,将新数组赋给原数组。

? ? ? ? 读方法不加锁,提高了并发效率。适合读多写少的操作。

三、CopyOnWriteArraySet

? ? ? 线程安全,不存在重复元素。底层使用CopyOnWriteArrayList,添加元素时判定元素是否存在。(使用循环判断)??

四、辅助类 CountDownLatch

? ? ? ? 允许一个线程等待其他线程执行完成后再执行。

十二、线程池

????????池:

????????创建出一定数量连接对象放入池子,有连接到来时,从池子中获取对象,使用完后不销

毁,还回到池子中即可。

? ? ? ? 优点:

????????减少创建销毁的开销。

线程池:

????????java从jdk5开始就有了线程池的实现。

? ? ? ? ?分为两类?Executors和ThreadPoolExecutor,其中阿里巴巴开发规约中规定使用

ThreadPoolExecutor实现。

????????ThreadPoolExecutor中可以准确的控制创建的数量,最大等待数量,拒绝策略等。

? ? ? ???ThreadPoolExecutor构造方法中的7个参数:

????????1.corePoolSize 5 核心池子的数量(大小),默认是先不创建线程,有任务到达后,再创建,之后

就不销毁了。

????????2.maximumPoolSize 10 最大池子数量。

????????3.keepAliveTime: ?非核心线程池中的线程,在多久之后没有任务执行时,销毁.

????????4.TimeUnit ?时间单位

????????5.workQueue ?等待队列 ?设置队列数量 20

????????6.threadFactory 创建线程工厂;

????????7.handler ?拒绝策略.

文章来源:https://blog.csdn.net/m0_61976036/article/details/135698767
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。