公平锁/非公平锁
并发包中的ReentrantLock 可以创建公平锁或者非公平锁,默认是非公平锁
Java 多线程值ReentrantLock 与Condition
公平锁
指多个线程按照申请锁的顺序来获取锁
在并发环境中,每个线程都会先查看锁的FIFO 等待队列,若为空,就占有锁,否则,则进队
非公平锁
指多个线程获取锁的顺序不是按照申请锁的顺序来的,在高并发情况下,有可能会造成优先级反转或者饥饿现象
线程一上来就尝试占有锁,若尝试失败,则再采用类似公平锁的那种策略
优点:非公平锁的吞吐量比公平锁大
对于Synchronized 而言,也是一种非公平锁
可重入锁(递归锁)
指的是同一线程在外层函数获得锁之后,内层的递归函数依然可以获得该锁
换句话说:线程可以进入任何一个它已经拥有的锁同步着的代码块
ReentrantLock/Synchronized 是一个典型的可重入锁
可重入锁作用:避免死锁
自旋锁
指的是在尝试获取锁的时候不会立即阻塞,而是采用循环的方式去尝试获取锁
优点:减少上下文的切换
缺点:循环会消耗CPU
典型例子:CAS(AtomicInteger)
读写锁
- 读-读共存
- 读-写不共存
- 写-写不共存
1 |
|
CountDownLatch
让一些线程阻塞,直到其余线程完成为止
1 | public class Test { |
CyclicBarrier
1 | public class Test { |
Semaphore
信号量,控制对共享资源的访问
1 | public class Test { |
AQS
如果被请求的共享资源处于空闲状态,则当前请求资源的线程就会设置为工作线程,并且将当前资源设置为锁定状态;如果被请求的共享资源处于锁定状态,则需要一套线程阻塞以及线程被唤醒时锁分配的机制,这个机制是使用CLH 队列锁实现的,将暂时获取不到锁的线程放到队列中
典型例子:ReentrantLock, Semaphore, ReentrantReadWriteLock等等
AQS 定义两种资源的共享方式
- Exclusive(独占):只能有一个线程去独占共享资源,公平锁、非公平锁(Synchronized)
- Share(共享):多个线程可以同时去执行,如Samephore、CycliBarrier、CountDownWatch