多线程并发场景下,如何实现锁
1.使用java自带的 synchronized 关键字实现锁
使用 java.util.concurrent.locks.ReentrantLock 实现锁
synchronized 和 ReentrantLock 的对比
锁 | |||||
synchronized | 独占锁 | 可重入 | 不可中断 | 非公平 | synchronized修饰方法 synchronized{} 修饰代码块,修饰类 |
ReentrantLock | 独占锁 | 可重入 | 可中断 | 默认非公平 可实现公平锁 | lock.lock() lock.unlock() |
名词解释:
独占锁:只能由同一个线程占用锁,另一个线程当锁没被释放不能占用
可重入:同一个线程可多次占用同一个锁,锁计数器加1;释放的时候,只有锁所计数器为0;锁才能被释放
不可中断:等待锁的进程得一直等待,不能放弃
可中断:thread.interrupt () 两个线程在争夺锁;第一个线程占用锁,第二个线程得一直等待;第一个线程interrupt 中断之后(此时不是通过unlock的方式),第二个线程可以拥有该锁;
公平锁:根据线程等待锁的时间长短;等待时间长的线程优先占有锁
2.使用AtomicBoolean
原子性的boolean对象,可以原子性的设置boolean值
private AtomicBoolean isLock = new AtomicBoolean(false);
compareAndSet(boolean expect, boolean update)
3种方式:自旋、yield+自旋、sleep+自旋
自旋
while(!isLock){}
浪费cpu的时间
yield+自旋
while (!lock()) {
//获取不到锁,主动让出CPU资源
Thread.yield();
}
yield+自旋适用于两个线程竞争的情况,如果线程太多,频繁的yield也会增加CPU的调度开销。
sleep+自旋
while (!lock()) {
//获取不到锁的线程,暂时休眠1ms,释放CPU资源
SleepUtil.sleep(1);
}
sleep时间不可控;不知道该sleep多长时间;