LongAdder,CyclicBarrier,MarriagePhaser,Semaphore
效率#
线程数特别多的时候
Longadder > Atomic > synchroinzed
Longadder内部使用了分段锁
Longadder是LongAccumulator的一种特殊形式
ReentrantLock,synchronized对比#
cas vs sync#
trylock
lockinterupptibly
公平锁和非公平锁的切换#
- 如果一个线程组里,能保证每个线程都能拿到锁,那么这个锁就是公平锁
- 相反,如果保证不了每个线程都能拿到锁,也就是存在有线程饿死,那么这个锁就是非公平锁
CyclicBarrier#
允许一组线程全部等待彼此达到共同屏障点的同步辅助。
循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此
屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用
A CyclicBarrier
支持一个可选的Runnable
命令,每个屏障点运行一次,在派对中的最后一个线程到达之后,但在任何线程释放之前
在任何一方继续进行之前,此屏障操作对更新共享状态很有用
实现原理#
在CyclicBarrier的内部定义了一个Lock对象,每当一个线程调用await方法时,将拦截的线程数减1,然后判断剩余拦截数是否为初始值parties
如果不是,进入Lock对象的条件队列等待。
如果是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列中,这些线程会依次的获取锁、释放锁
构造方法 #
CyclicBarrier(int parties)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待它时,它将跳闸,并且当屏障跳闸时不执行预定义的动作
CyclicBarrier(int parties, Runnable barrierAction)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待时,它将跳闸,当屏障跳闸时执行给定的屏障动作,由最后一个进入屏障的线程执行
方法#
- int await() 等待所有 parties已经在这个障碍上调用了 await
- int await(long timeout, TimeUnit unit) 等待所有 parties已经在此屏障上调用 await ,或指定的等待时间过去
- int getNumberWaiting() 返回目前正在等待障碍的各方的数量
- int getParties() 返回旅行这个障碍所需的parties数量
- boolean isBroken() 查询这个障碍是否处于破碎状态
- void reset() 将屏障重置为初始状态
测试#
CountDownLatch和CyclicBarrier的比较#
- CountDownLatch是线程组之间的等待,即一个(或多个)线程等待N个线程完成某件事情之后再执行
- CyclicBarrier则是线程组内的等待,即每个线程相互等待,即N个线程都被拦截之后,然后依次执行
- CountDownLatch是减计数方式,而CyclicBarrier是加计数方式
- CountDownLatch计数为0无法重置,而CyclicBarrier计数达到初始值,则可以重置
- CountDownLatch不可以复用,而CyclicBarrier可以复用
CyclicBarriar限流#
#
复杂操作
- 数据库
- 网络
- 文件
并发执行,不同的线程执行不同的操作
MarriagePhaser(不重要)#
phase 是阶段的意思
Phaser是按照不同阶段执行线程的,就像是结合了CountDownLatch和CyclicBarrier,它本身维护着一个叫 phase 的成员变量代表当前执行的阶段
这是一个结婚的场景,自定义一个MarriagePhaser 继承 Phaser 重写Phaser的onAdvance方法定义了4个阶段(进入下一个阶段时该方法被自动调用)
arrive,eat,leave,hug,所有人都能执行前三个方法,hug只能由新郎新娘执行
读写锁,ReadWriteLock#
共享锁 + 排他锁,写锁排他,读锁共享
ReentrantReadWriteLock有如下特性#
非公平模式(默认)#
当以非公平初始化时,读锁和写锁的获取的顺序是不确定的
非公平锁主张竞争获取,可能会延缓一个或多个读或写线程,但是会比公平锁有更高的吞吐量
公平模式#
当以公平模式初始化时,线程将会以队列的顺序获取锁
当当前线程释放锁后,等待时间最长的写锁线程就会被分配写锁;或者有一组读线程组等待时间比写线程长,那么这组读线程组将会被分配读锁
当有写线程持有写锁或者有等待的写线程时,一个尝试获取公平的读锁(非重入)的线程就会阻塞
这个线程直到等待时间最长的写锁获得锁后并释放掉锁后才能获取到读锁
可重入#
允许读锁可写锁可重入。写锁可以获得读锁,读锁不能获得写锁
锁降级#
允许写锁降低为读锁
中断锁的获取#
在读锁和写锁的获取过程中支持中断
支持Condition#
写锁提供Condition实现监控
提供确定锁是否被持有等辅助方法
Semaphore(信号量)#
acquire,获得许可
release,释放
限流
Exchanger#
交换数据,两两交换,交换结束后,两线程继续向下执行
游戏中两人交换装备
作者:BigBender
出处:https://www.cnblogs.com/BigBender/p/14432962.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2020-02-23 一元积分学几何应用
2020-02-23 B1027. 打印沙漏
2020-02-23 git push 不用输入用户名和密码