1. 问题背景
在 Java 并发编程中,锁有两种实现:
-
synchronized
-
lock
在面试中,从解决并发的功能角度来说,它们都能通过上锁的方式,解决对资源的抢占问题。
但是它俩的区别是什么呢?
2. synchronized与lock的区别
2.1 底层实现机制不同
-
synchronized: Java 中的关键字,是由 JVM 来维护的,是 JVM 层面的锁。
-
lock:是 JDK5 以后才出现的具体的类,使用lock是调用对应的API,是API层面的锁
synchronized 是底层是通过 monitorenter 进行加锁,通过monitorexit来退出锁的。
实现机制是底层是通过monitor对象来完成的,其中的 wait/notify 等方法也是依赖于 monitor 对象的。
而 lock 是通过调用对应的 API 方法来获取锁和释放锁的。
2.2 使用方式不同
-
synchronized 是隐式锁。
-
lock 是显示锁。
所谓的显示和隐式就是在使用的时候,使用者要不要手动写代码去获取锁和释放锁的操作。
在使用 synchronized 关键字的时候,由程序自动获取锁和释放锁了,如果非逻辑问题的话话,是不会出现死锁的。
在使用 lock 的时候,我们使用者需要手动的获取和释放锁。如果没有释放锁,就有可能导致出现死锁的现象。手动获取锁方法:lock.lock()。释放锁:unlock方法。需要配合tyr/finaly语句块来完成。
2.3 等待的处理方式不同
-
synchronized 是不可中断的,除非抛出异常或者正常运行完成。
-
lock 可以中断的。
lock 调用设置超时方法 tryLock(long timeout ,timeUnit unit)
,也可以调用 lockInterruptibly()
放到代码块中,然后调用 interrupt()
方法可以中断。
2.4 加锁的时候是否可以公平
-
synchronized 非公平锁。
-
lock 两者都可以的,默认是非公平锁,在其构造方法的时候可以传入Boolean值来决定。
2.5 性能比较
-
synchronized 由于给jvm 托管,在 Java1.5 中性能较为低效, Java 1.6 中进行了优化。
-
lock 相比 synchronized 性能要好些。
2.6 锁的方式
-
synchronized 悲观锁。
-
lock 乐观锁。