多线程高并发
文章目录
synchronized
修饰静态方法锁的是class,非静态锁方法锁的是this,只有拿到这个对象才可以继续执行代码。
synchronized是可重入锁:线程1的方法1调用线程2的方法2,判断是同一把锁,在同一个线程,可以调用。
- synchronized的锁升级 (hotsport)
锁升级过程
- 无锁态 markword标记 0 0 1
- 只有一个线程,markword记录线程id,升级为偏向锁 markword 标记 1 0 1
- 有线程争用, 升级为自旋锁 markword 标记 0 0
- 自旋10次后,升级为重量级锁 --> 跟OS申请锁,进入等待队列。markword标记 1 0
volatile
- 保证线程可见性
mesi缓存一致性协议, 参考JMM。 - 禁止指令重排序
JVM规范要求volatile前后得加屏障,屏障两边不能指令重排,保障有序。具体参考JMM。
- 指令重排
为了提高CPU性能处理,可能将后面的读缓存命令优先执行。重排需要遵守as-if-serial语义:不管怎么重排序,程序的执行结果不能被改变。
CAS(无锁优化 自旋)
-
Comparre And Set/Swap
CPU原语支持 -
ABA问题
可以加version控制 -
AtomicXXX比sync效率高, 没有加锁
ReentrantLock
必须手动解锁,写在finally中。
方法
- lock.lock()加锁、lock.unLock()解锁
- Condition c = lock.newCondition():
c.await(): 当前线程等待
c.signalAll(): 唤醒等待线程
condition 本质是等待队列
ReentrantLock vs synchronized
cas
tryLock 是否获取锁
lockInterruptibly 没有获取锁就等待,使用interrupt()终止。
公平和非公平锁
CountDownLatch – 倒计时/计数器
- CountDownLatch latch = new CountDownLatch(10);
latch.countDown(); -1
latch.await(); 为 0 时执行后面的代码。
CyclicBarrier – 栅栏,满人执行。
- 两个参数 (int count , Runnable r)
到达 count 线程执行 r 方法
await() : 达到 count 线程才执行后面的代码,然后继续拦着等到线程到达指定数字。
Phaser – 分阶段执行(栅栏组)
- 继承 Phaser 重写 onAdvance(int 第几个阶段(0开始), int 有几个人参加)
return true 时,Phaser 栅栏组结束。 - phaser.bulkRegister(int 设置参加人数)
phaser.arriveAndAwaitAdvance(), 等待到达(设置参加的人数时触发onAdvance )并继续前进。
phaser.arriveAndDeregister(), 离开。
ReadWriteLock – 读写锁
- ReadWriteLock readWriteLock = new ReenTrantReadWriteLock()
共享锁 :readWriteLock.readLock():读数据线程可以一起读
排它锁 :readWriteLock.writeLock():写数据一个个写
Semaphore – 控制线程运行数量
- Semaphore s = new Semaphore(允许线程执行数):最多允许运行多少个线程。
s.acquire() : 从 s 中获得许可才可继续运行。 获得一个许可 允许线程执行数-1
s.release() : 释放获取的许可, 运行线程执行数 +1
Exchanger – 交换器
两个线程交换数据
exchange.exchange(交换数据) : 调用此方法阻塞等待。
LockSupport
- 阻塞当前线程LockSupport.park(), LockSupport.unpark(指定park阻塞的线程) 唤醒阻塞的线程。
- unpark 可以在 park 之前调用。
Synchronized和ReentrantLock
- synchronized自动解锁,ReentrantLock手动解锁
- synchronized4中锁状态升级,ReentrantLock底层CAS实现