Lock锁

176 阅读3分钟

一、synchronized与reentrantLock的区别?

  1. synchronized是隐式锁,reentrantLock是显式锁
  2. 功能角度:reentrantLock具有synchronized不具备的高级功能 | 功能 | 详情 | | --- | --- | | 等待可中断 | 持有锁的线程长期不释放锁,等待的线程可以放弃等待 | | 带超时的获取锁尝试 | 在指定的时间内获取锁,未成功获取锁则返回 | | 获取排队信息 | 能够判断是否有线程在排队等待锁 | | 可以响应中断请求 | 获取到锁的线程被中断,能响应中断,释放锁 | | 实现公平锁 | 是 |
  3. 锁释放角度:synchronized是JVM层面实现的,异常时能够自动释放锁;reentrantLock则是代码实现,需要把unlock放入finally块中
  4. 性能角度:synchronized早期性能低,java6改进后,在竞争不激烈时性能要更优秀,高竞争情况下则不如reentrantLock

二、synchronized的实现原理?修饰不同对象时锁住的是什么?

  1. 对于用synchronized修饰的代码块,使用monitorenter和monitorexit指令放在代码块前后
修饰对象锁住对象
实例方法对象实例
静态方法当前类的class实例
代码块传入synchronized的对象实例

三、synchronized在java6做了哪些优化?

  1. 无锁
  2. 偏向锁:JVM会认为只有某个线程才会执行同步代码,只要线程来执行代码了,会比对线程ID是否相等,相等则当前线程能直接获取得到锁
  3. 轻量级锁:线程ID不相等后,CAS获取不成功则升级为轻量级锁。在栈帧下创建LockRecord,将MarkWord的信息拷贝进去,且有个Owner指针指向加锁的对象
  4. 重量级锁:CAS无法将锁对象的MarkWord替换为指向LockRecord的指针,则升级为重量级锁,使用monitor对象

四、锁升级的时机是什么时候?

  1. 偏向锁只有在其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁(被动释放,此时会发生锁升级)
  2. 轻量级锁在加锁失败进行CAS达到一定次数后(自旋锁默认的次数为 10 次),就会升级为重量级锁

五、AQS了解吗?

  1. 是什么:一个维护先进先出队列和state状态变量的框架
  2. 什么时候使用:用于多线程争夺资源阻塞的情况
  3. 入队出队的角度:既可用于实现公平锁也可以实现非公平锁,通过在每个线程进队时是否CAS竞争一下锁来实现。节点设置为signal状态,表示后继节点需要被唤醒,解锁,将state置0,并唤醒头节点的下一个合法节点
  4. 资源共享角度:独占式(reentrantLock)、共享式(semaphore)

六、synchronized是可重入锁吗?

每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。