目录
day3
一,JUC同步工具
1,LongAdder , Atomic ,sync
2,LOCK
3,公平锁
4,ReentrantLock vs sync
5,CountDownLatch 倒数的门栓
6,CyclicBarrier 循环栅栏
7,Guava RateLimiter 限流
8,MarriagePhaser 1.7 循环栅栏
9,ReasWiriteLock 读写锁
10,Semaphore 信号灯
11,Exchange 交换器
day3
一,JUC同步工具
1,LongAdder , Atomic ,sync
1,LongAdder , Atomic ,sync
LongAdder > Atomic > sync 高并发下效率高
Atomic > sync
CAS(无锁(乐观锁)优化 自旋)
线程多,操作时间短的情况下,自旋锁大于系统锁的性能
LongAdder > Atomic
CAS(无锁(乐观锁)优化 自旋)的基础上
内部分段:例如1000个线程,分成4个250个线程在一起工作,然后把这个4个一加。
线程数特别多,有明显优势。
2,LOCK
.可重入锁
可重入锁:锁一次后,可以对同样的锁再锁一次 。线程1获得锁,当线程1执行完任务再次进入的时候,在锁的头上记录有线程的标识号,对比后发现一致,继续执行,不需要额外申请。
子类实现调用父类。
sync m1 {}
sync m2 {}
new Thread(rl:m1).startt();
new Thread(rl:m2).startt();
//这时1先拿到锁,2永远最后执行
//但是如果在1里面调用2,两个方法都可以执行。
sync 方法 == sync(this) 是同一把锁
.reentrantLock
使用reentrantLock 重写例子,与sync 不同的是,需要在finally里解锁
.tryLock 尝试申请时间
在指定之间内,尝试获取锁
.lockInterruptibly 可以对interrput()方法做出响应
sync
一旦wait之后,必须notify才能醒来。
lock
可以被打断的加锁,使用interrput(),可以打断加锁
---todo
3,公平锁
new ReentrantLock(true);
谁等待在前面,谁先执行。而不是一起抢。就是排不排队
先到得线程在等待队列中,
公平锁:新来的线程会查看队列中是否有线程,如果有,进入队列等待;
非公平锁:新来的线程直接抢锁是可能抢到得。
不是绝对的公平,只是先取队列中的。你还没排队,我买完东西后,又排队了。
4,ReentrantLock vs sync
锁的类型·
trylock
lockInterruptibly
公平和非公平
5,CountDownLatch 倒数的门栓
倒数的门栓:等待结束
await();//阻塞
countDown();//-1,本身是原子的
也可以使用join
6,CyclicBarrier 循环栅栏
循环栅栏:
CyclicBarrier cb = new CyclicBarrier (20,new Runnable(){
run(){
满20人,发车
}})
CyclicBarrier cb = new CyclicBarrier (20,()-> );
cb.await();//加人
读取数据场景
数据库,网络,文件必须都读到才能执行,
顺序执行太慢,并发执行并使用CyclicBarrier大大节约执行时间。
使用时间比较:1+2+3 1,2,3里最长的
7,Guava RateLimiter 限流
场景:限流
8,MarriagePhaser 1.7 循环栅栏
arriveAndAwaitAdvance();//等待到达
arriveAndAwaitderegistert();//阶段停止
按不同的阶段执行:分阶段执行,需要多个参与的。(遗传算法)
循环栅栏,多个关卡,每个关卡的线程数。
场景:结婚 到达,吃,离开,洞房
不同的人有不同的阶段
所有人到才能开席,新浪新娘才能洞房
9,ReasWiriteLock 读写锁
读(共享)写(排他,互斥)锁
读多,写少,保证数据的一致性。读写都需要加锁,避免脏读。
10,Semaphore 信号灯
限流,同时只允许多少个线程执行。高速口,5个收费窗口
线程执行去获取锁,才能执行。限制的不是多少线程,而是限制多少线程同时执行。
公平,非公平
11,Exchange 交换器
交换器,两个线程交换数据使用。阻塞交换,继续执行。
多个阻塞再两两交换。
游戏中交换装备,DNF交易
乐关锁:aqs,悲观锁:sync ,自旋锁:aqs,读写锁(排它锁,共享锁):lock,分段锁:ConcurrentHashMap,Segment



