上一篇,也就是第12篇的内容可以出好几道面试题,面试题如下
1.说说线程安全问题?
- 线程安全:线程安全指的是要控制多个线程对某个资源的有序访问或者修改,而这些线程之间没有冲突。
- 而线程安全问题指的是多个线程同时访问一个资源时产生的数据污染或者丢失的情况
- 产生线程安全问题的两个条件
- 多个线程操作共享的数据
- 操作共享数据的线程代码有多条
2.ReentrantLock常见的方法有哪些?
lock():用于获取锁
unlock():用于释放锁
trylock():尝试获取锁
trylock(long timeout ,TimeUnit unit);:在一定的时间内尝试去获取锁,而不是等待一段时间去获取
getHoldCount():计算lock方法的使用此时。
getQueueLength():返回正在排队等待获取此锁的线程数
isFair():是否为公平锁
3.ReentrantLock有哪些优势?
- 具备非阻塞方式获取锁,比如:tryLock()
- 可以中断所获取的锁,比如:使用interruptibly()方法,线程获得锁,会抛出异常并释放当前获得的锁。
- 可以在指定时间获取锁,比如:使用trylock(long timeout ,TimeUnit unit)
4.ReentrantLock怎么创建公平锁?
new ReentrantLock()默认创建的为非公平锁
new ReentrantLock(true)默认创建的为公平锁
5.ReentrantLock的lock方法和lockInterruptibly有什么区别?
前者在获取线程的途中如果所在的线程中断,会忽略异常继续等待获取线程,而后者则会抛出InterruptdException异常。
6.synchronized是怎么实现锁升级的?锁升级的目的是?
在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再次进入的时候会先判断 threadid 是否与其线程 id 一致,如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁,此过程就构成了 synchronized 锁的升级。
锁的升级的目的:锁升级是为了减低了锁带来的性能消耗。在 Java 6 之后优化 synchronized 的实现方式,使用了偏向锁升级为轻量级锁再升级到重量级锁的方式,从而减低了锁带来的性能消耗。
7.synchronized和reentrantlock的区别
两种都是保证线程安全的,它们的区别如下:
- reentrantlock使用起来较为灵活,但必须有释放锁的动作
- reentrantlock只能用于代码块,而不能用于方法,而前者都可以
- reentrantlock必须手动的获取锁和释放锁,而前者不用
- reentrantlock性能较高