Java synchronized关键字与ReentrantLock区别

synchronized关键字与ReentrantLock区别

从以下几个方面阐述两者差异
1 应用场景:
synchronized: 不能显示的释放锁,使用不灵活。在某些需要灵活控制锁的获取和释放场景下不适用。
ReentrantLock: 可以通过 lock\tryLock、unlock等方便的对程序加锁以及释放锁,使用起来更灵活。
2、使用方式
synchronized:修饰普通方法、静态方法、代码块。
ReentrantLock:Lock接口的实现类,通过ReentrantLock实例对象的 lock和unlock方法加锁和释放锁。ReentrantLock实例方法 lock、unlock
3、实现原理
synchronized:通过对象头中的ObjectMonitor 监视器记录获取对象锁的线程。其他没有获得锁的线程会被阻塞。
ReentrantLock: 通过AQS队列来实现阻塞线程的记录,具备FIFO顺序性。condition队列来实现synchronized 锁的 挂起,condition记录着 condition.wait()的线程,通过condition.signal唤醒的线程会有condition加入AQS队尾,从而等待获取锁执行。
4、线程通信
synchronized: 由synchronized 实现原理可知,其是通过ObjectMonitor来实现重量级锁,通过Object的wait、notify/notifyAll 来实现线程通信。
ReentrantLock 则是通过AQS队列与Condition队列实现线程挂起以及线程阻塞。
唤醒顺序synchronized的notify会随机唤醒一个处于wait状态的线程,而ReentrantLock由于condition队列的存在,调用一次signal() 会从condition取出头节点放入AQS等待队列,因此唤醒具有顺序性,即先wait的线程先唤醒。
5、公平性
ReentrantLock 实现了公平锁和非公平锁,公平锁和非公平锁在源码中有两处差别
1)、非公平锁:当一个线程获取锁失败【已有线程获取锁】,加入双向链表【同步队列】之前会再次尝试获取锁,而公平锁不会
2)、在tryAcquire()获取锁时,非公平锁会再次尝试获得锁,而公平锁会判断队列里面是否有Node节点【阻塞等待获取锁的线程】,如果存在则不会再次尝试获得锁
Synchronized 的notify会随机唤醒一个处于wait状态的线程,也可以调用waitAll()唤醒所有等待的线程,但都是非公平的

​​​​

你可能感兴趣的:(java并发编程,synchronized原理)