废话少说,直接上正文
1. synchronized vs Lock
存在层次上
synchronized是java中的关键字,在JVM层面上
Lock是一个接口
锁的释放
synchronized:1. 代码执行完毕 2. 程序出现异常
Lock:在finally中必须释放锁,不然容易造成线程死锁
锁的获取
synchronized:假设A线程获得锁,B线程等待。如果A线程阻塞,B线程回一直等待
Lock:lock可以获取锁的状态,尝试获得锁,如果没有获得到锁,线程可以不用一直等待。
死锁
synchronized:在发生异常时候会自动释放占有的锁,因此不会出现死锁。
Lock:发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,不然可能会引起死锁的产生
锁的状态
synchronized:无法判断
Lock:可以判断
锁的类型
synchronized:可冲入 不可中断 非公平
Lock:可重入 可判断 可公平(两者皆可)
性能
synchronized:少量同步
Lock:大量同步
调度
synchronized:使用Object对象本身的wait、notify、notifyAll调度机制
Lock:可以使用Condition进行线程之间的调度
用法
synchronized:可以修饰在类,方法,代码块
Lock:一般使用ReentrantLock类做为锁
底层实现
synchronized:底层使用指令码方式来控制锁的,映射成字节码指令就是monitorenter和monitorexit。当线程执行遇到moniterenter指令时会尝试获取内置锁,如果获取锁则锁计数器+1,如果没有获取则阻塞;当遇到monitorexit指令时锁计数器-1,如果计数器为0则释放锁。
Lock:底层时CAS乐观锁,依赖AbstractQueuedSynchronized类,把所有的请求线程构成一个CLH队列。
synchronized注意事项
- 锁对象不能为空,因为锁的信息都保存在对象头里。
- 作用域不宜过大,影响程序执行的速度,控制范围过大,编写代码也容易出错。
- 避免死锁
- 在能选择的情况,既不要用Lock也不要用synchronized关键字,而是JUC下的各种类