JUC编程
2025-02-28 14:56:44 0 举报
AI智能生成
包括乐观锁、悲观锁、公平锁、非公平锁、CAS、AQS、线程池、队列、原子类、同步工具类等
作者其他创作
大纲/内容
核心部分及工具类
锁机制
ReentrantLock :可重入互斥锁,支持公平/非公平模式,功能类似synchronized但更灵活
ReentrantReadWriteLock :读写分离锁,允许多线程同时读,写时独占
StampedLock :支持乐观读、悲观读和写锁,适合高并发场景
Condition :与ReentrantLock配合实现线程协调(类似wait/notify)
同步工具类
CountDownLatch :线程等待其他线程完成一组操作
CyclicBarrier :线程在屏障点等待,直到所有线程到达后继续执行
Semaphore :控制同时访问资源的线程数量
Exchanger :两个线程在同步点交换数据
Phaser :灵活的多阶段同步工具,支持动态调整参与线程
线程池
ThreadPoolExecutor :自定义线程池,支持核心/最大线程数、队列等参数
ScheduledExecutorService :定时任务线程池
Executors :工厂类,提供newFixedThreadPool、newCachedThreadPool等快捷创建方式
原子类
AtomicInteger/AtomicLong/AtomicBoolean :基本类型的原子操作
AtomicReference :引用类型的原子操作
AtomicStampedReference :带版本号的引用,解决ABA问题
LongAdder/DoubleAdder :高并发累加器,性能优于原子类
队列
BlockingQueue :阻塞队列接口,实现包括ArrayBlockingQueue、LinkedBlockingQueue
ConcurrentLinkedQueue :非阻塞线程安全队列
SynchronousQueue :直接传递元素的队列,无容量
ConcurrentHashMap
读操作无锁 :通过 CAS(Compare and Swap) 和 volatile 实现。
写操作:红黑树 + CAS + synchronized
高吞吐量 :适用于读多写少的场景
链表转红黑树:链表长度超过8
红黑树转链表:红黑树长度<6
插入或更新时,通过 CAS 更新节点
读操作 :完全无锁,通过 volatile 保证可见性
CAS(Compare And Swap)
乐观锁(无锁,冲突时重试)的一种实现方式
乐观锁(无锁,冲突时重试)的一种实现方式
CAS是一种无锁算法,通过硬件指令(如cmpxchg)实现原子操作,核心步骤:
1、比较内存值与预期值是否一致。
2、若一致,更新为新值;否则重试。
1、比较内存值与预期值是否一致。
2、若一致,更新为新值;否则重试。
优点
无锁设计,减少线程阻塞,适合低竞争场景
缺点
ABA问题 :一个线程值从A→B→A时,其他线程读取变量时无法感知其变化,导致CAS误判,可通过AtomicStampedReference代替AtomicInteger解决
AtomicStampedReference.compareAndSet(预期值,当前值,当前状态位,下一状态位)
此时要求预期值和当前状态位均匹配的情况下,才能更新成功
根据实际业务场景来决定是否使用,例如对过程有严格要求的情况下,可以使用AtomicStampedReference,只关注结果的情况下,可以不考虑此情况
自旋开销 :高并发下可能频繁重试,消耗CPU
AQS(AbstractQueuedSynchronizer)
锁状态通过CAS实现,但是整体的模式是悲观锁(锁获取失败进入阻塞队列,直到获取锁)
锁状态通过CAS实现,但是整体的模式是悲观锁(锁获取失败进入阻塞队列,直到获取锁)
AQS是JUC中锁和同步器的基础框架,全称是“Abstract Queued Synchronizer”。它是许多同步工具类(如ReentrantLock、CountDownLatch、Semaphore等)的核心实现。
ReentrantLock(true):公平锁,要排队
ReentrantLock(false):非公平锁,可插队,默认
通过lock和unlock加解锁
通过lockInterruptibly方法进行加锁,可以通过thread.interrupt主动中断锁的获取
通过newCondition实现按业务条件来释放并等待
具备重入性,同一个线程可以多次加锁,每加一次锁,计数器会+1,unlock会-1,直到0才会释放锁
ReentrantLock(false):非公平锁,可插队,默认
通过lock和unlock加解锁
通过lockInterruptibly方法进行加锁,可以通过thread.interrupt主动中断锁的获取
通过newCondition实现按业务条件来释放并等待
具备重入性,同一个线程可以多次加锁,每加一次锁,计数器会+1,unlock会-1,直到0才会释放锁
初始化CountDownLatch(任务数)
线程结束finally中,执行CountDownLatch.countDown,计数器减一
主线程CountDownLatch.await阻塞,等到计数器归0再继续执行
线程结束finally中,执行CountDownLatch.countDown,计数器减一
主线程CountDownLatch.await阻塞,等到计数器归0再继续执行
AQS的核心思想是通过一个状态变量 (state)和一个FIFO队列 来管理线程的获取和释放资源的过程:
状态变量:表示资源的状态(如锁是否被占用)。
FIFO队列:用于管理等待资源的线程。
状态变量:表示资源的状态(如锁是否被占用)。
FIFO队列:用于管理等待资源的线程。
AQS的工作原理
当线程尝试获取资源时,会调用tryAcquire方法。
如果获取失败,线程会被加入到等待队列中,并进入阻塞状态。
当资源被释放时,唤醒队列中的下一个线程。
当线程尝试获取资源时,会调用tryAcquire方法。
如果获取失败,线程会被加入到等待队列中,并进入阻塞状态。
当资源被释放时,唤醒队列中的下一个线程。
0 条评论
下一页
为你推荐
查看更多