一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
公平锁和非公平锁
原理举例
公平锁:多个线程对锁的竞争是差不多公平的
A执行了20次,B执行了19次,C执行了19次
特点:各个线程都会有执行的可能,但是效率相对于较低
实现逻辑:其中有个方法将多个线程放入队列中进行排队执行
非公平锁:
多个线程对锁竞争是不公平的
A执行20次,B执行0次,C执行1次
特点:锁的竞争很不公平,但是执行的效率较高
实现逻辑:直接进行业务执行,哪个线程能竞争到锁随意
new ReentrantLock()
的构造方法中可以传入boolean
参数,false
(默认)表示非公平锁
公平锁优缺点
优点:不会出现有的线程被饿死的情况
缺点:效率相对于而言低一些。需要不停的唤醒阻塞线程
公平锁实现
通过维护一个线程的队列。每次获取锁必须是排队的第一个,释放锁之后就自动去队列末尾继续排队等待
可重入锁和非可重入锁
概念和实例
递归锁:一个线程在外层获取到锁之后进入内层会自动获取锁(锁的对象是同一个)。
public void static main(String[] args){
synchronized (this){
//xxxxx
synchronized(this){
//xxxxx
}
}
}
锁的内部如果还有锁,该线程都可以访问。也就是多重锁,只要线程竞争到了锁资源,就可以访问到最内部也不用再重新竞争锁
synchronized
是隐式的可重入锁
ReentrantLock
是显式(需要手动上锁和解锁)的可重入锁
NonReentrantLock
不可重入锁。
ReentrantLock和NonReentrantLock都继承AQS,其中维护了一个status来记录重入次数。
优点
优点:一定程度降低死锁的情况
锁的范围(对象实例和类对象)
普通方法上加上synchronized
锁住的是单独对象的这个方法
静态方法(static)加上synchronized
锁住的是所有对象的这个方法