ReentrantLock 与 synchronized对比
最近有在阅读Java并发编程实战这本书,又看到了ReentrantLock和synchronized的对比,发现自己以前对于RenntrantLock的理解很片面,特此做一番总结,如果有总结不到位的,欢迎指出
java.util.concurrent.locks
接口 Lock
为什么需要Lock?
java.util.concurrent.locks
接口 Lock
Lock提供了一种如条件的、可轮训的、定时的以及可以终端的获取锁的操作,所有的加锁方式和解锁方式都是显式的。
public class Lock { private boolean locked = false; public Lock() { } public final synchronized void lock() throws InterruptedException { while(this.locked) { this.wait(); } this.locked = true; } public final synchronized void unlock() { this.locked = false; this.notifyAll(); } }
Lock是JAVA5.0出现的,它的出现并不是为了替代synchronized,而是在synchronized不适用的时候使用。
那么synchronized有什么局限性呢?
- 无法中断一个正在获取锁的线程
当一个线程想获取已经被其他线程持有的锁时,就会发生堵塞,假设已经持有锁的线程一直不释放锁,那么线程就会一直等待下去。
- 无法指定线程执行时间
比如,想要A线程执行某个操作,该操作在5分钟之内没有完成,就返回失败,5分钟之内完成就返回成功。对于synchronized内置锁是做不到的,而ReentrantLock是可以做到的。
相同点:
- 独占锁: 一次只允许一个线程访问
- 可重入锁: 一个线程可重复获得自己已获得锁,不会发生死锁。简单来说,递归的时候不会发生死锁
不同点:
- Lock不是java内置的,synchronized是JVM内置的,因此是内置特性。
- 释放锁的方式:
- Lock 必须要在finally中手动释放锁
- synchronized 会根据锁区域代码自动执行完毕,或者发生异常,JVM会自动释放锁
ReentrantLock的使用:
基本使用
Lock lock = new ReentrantLock(); lock.lock(); try { //.... } finally { lock.unlock(); }