- 1、ReentrantLock和synchronized区别
锁的本质是:竞争。锁是一个对象。
相同:都是加锁等待
不同:synchronized -- 被动等待 -- 其他线程释放锁
ReentrantLock -- 更灵活 -- 锁的退出节点可控
具体实现:
synchronized是由JVM提供实现的,C语言编写的。和操作系统中监视器模型类似的一种实现。
不要求会读C语言,所以面试一般问【偏向锁、轻量级锁、重量级锁】ReentrantLock 大部分是由Java代码实现的。
要读懂Java编写的【底层原理实现】
------常用方法--------
lock.lock(); // 抢锁 持续等待
lock.tryLock(); // 获取在给定等待时间内空闲的锁。尝试获取锁一次
lock.unlock(); // 释放锁
------调用--------
------部分源码--------
------自定义实现lock锁--------
- 2、可重入锁是怎么做到的。可重入锁也叫自旋锁。
synchronized和java.util.concurrent.locks.ReentrantLock都是可重入锁。
简单面试问使用,深度面试问原理。
可重入锁,简单来说,就是一个加锁的计数。
可重入锁与不可重入锁对比,简单来说就是:可重入锁会多两个属性(1、获得该锁的线程;2、获得该锁的次数),根据第一个属性判断,如果是持有该锁的那个线程又来lock,不会被阻塞(wait),而是在上锁的次数加一(表示这个线程又锁了一次(重入)),只有该线程unlock的次数达到上锁的次数(即第二个属性等于0),才会唤醒其他线程。
为什么需要可重入锁?
所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞。
如下:不可重入锁会出现死锁问题。
当A方法获取lock锁去锁住一段需要做原子性操作的B方法时,如果这段B方法又需要锁去做原子性操作,那么A方法就必定要与B方法出现死锁。这种会出现问题的重入一把锁的情况,叫不可重入锁。调用B方法,必须先释放锁。
可重入锁的实现原理:
![]()
- 3、公平锁和非公平锁有什么区别
默认使用非公平锁(FairSync和NofairSync)
现象:创建多个线程,不同的线程抢到锁的次数不一样,有些线程次数之多,2倍甚至更大。甚至有极端情况,一定时间内,出现抢不到锁的线程,称为 线程饥饿。
如下图:创建5个线程(图1),公平锁和非公平锁抢到锁的次数结果对比(图2)
非公平锁 (可以插队) 优点:逻辑更加直接,所以性能由于公平锁
参考:面试官:说一下公平锁和非公平锁的区别?_慕课手记 (imooc.com)
原理:
------自己实现一个简单的公平锁-------