这两个锁大部分人都能知道一二。接下来从几个方面进行说明。
补充下,lock的实现类ReentrantLock和Synchronized都是可重入锁。
1.底层实现不同
Synchronized是关键字,底层是由c++进行实现的,是JVM层面的锁。而lock是接口,是由java代码实现的,是调用对应的方法来进行加锁,是api层面的锁
synchronized底层是基于monitor对象来实现加锁和释放锁的。这里解释下什么是monitor:monitor中有主要的三个属性,waitset,entryset,owner。 一个是等待队列,一个是阻塞队列,一个是当前拥有锁的线程。这也是为什么wait和notify的调用要在syn块儿中。因为只有在同步代码块或者是同步方法中,JVM才会调用 monitor 对象。
而lock是基于aqs对api的调用,进行加锁。
2.使用方法不同
synchronized是隐式锁,lock是显示锁。
隐式锁就是,上锁和释放锁不需要我们手动进行
显示锁就需要我们手动进行上锁和释放锁
在使用sync关键字的时候,程序能够自动获取锁和释放锁。那是因为当sync代码块执行完成之后,系统会自动的让程序释放占用的锁。Sync是由系统维护的,如果非逻辑问题的话,是不会出现死锁的。
在使用lock锁时,我们需要手动进行上锁和释放锁,否则可能会造成死锁现象,上锁:lock()。释放锁:unlock()
3.是否可以中断锁的等待。
synchronized对于锁不可以进行中断操作。
lock可以对锁的等待进行终端操作。
1.使用**tryLock(long timeout ,timeUnit unit)**方法设置超时时间,如果在这个时间内都还没获得锁,就不会在这死等,就会执行下面的代码。
2.可以使用lockInterruptibly(),可以对该线程进行打断操作,调用interrupt()方法。
4.加锁的时候是否公平
synchronized是非公平锁。
lock是可公平锁,也可是非公平锁。默认是非公平。可以通过在创建锁对象时,在构造器中加入boolean参数,true为公平锁,false为非公平锁。
5.条件变量(等待队列)和阻塞队列
synchronized中的monitor只有一个等待队列,和一个阻塞队列。要么随机唤醒一个,要么全部唤醒,唤醒不准确
lock可以通过newCondition设置多个条件变量,可以精确的进行唤醒。也只有一个阻塞队列。
本文使用 文章同步助手 同步