ReentrantLock 可重入锁
ReentrantLock,可重入锁,是一种递归无阻塞的同步机制。它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大、灵活的锁机制,可以减少死锁发生的概率。
公平锁与非公平锁
ReentrantLock还提供了公平锁也非公平锁的选择,构造方法接受一个可选的公平参数(默认非公平锁),当设置为true时,表示公平锁,否则为非公平锁。
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
公平锁与非公平锁的区别在于公平锁的锁获取是有顺序的。但是公平锁的效率往往没有非公平锁的效率高,在许多线程访问的情况下,公平锁表现出较低的吞吐量。
ReentrantLock与synchronized的区别
- 与synchronized相比,ReentrantLock提供了更多,更加全面的功能,具备更强的扩展性。例如:时间锁等候,可中断锁等候,锁投票。
- ReentrantLock还提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活,所以在多个条件变量和高度竞争锁的地方,ReentrantLock更加适合(以后会阐述Condition)。
- ReentrantLock提供了可轮询的锁请求。它会尝试着去获取锁,如果成功则继续,否则可以等到下次运行时处理,而synchronized则一旦进入锁请求要么成功要么阻塞,所以相比synchronized而言,ReentrantLock会不容易产生死锁些。
- ReentrantLock支持更加灵活的同步代码块,但是使用synchronized时,只能在同一个synchronized块结构中获取和释放。注:ReentrantLock的锁释放一定要在finally中处理,否则可能会产生严重的后果。
- ReentrantLock支持中断处理,且性能较synchronized会好些。
可使用的方法
//如果该锁没有被其他线程获得,则获得当前锁;如该线程已经获得当前锁, 则当前锁的count加1(即可重入);否则阻塞该线程,直到当前锁可被获得 public void lock() { sync.lock(); } //尝试获取锁直到该线程被中断 public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } //只有在当前锁未被别的线程获取时才获取锁,返回true, 否则返回false。 public boolean tryLock() { return sync.nonfairTryAcquire(1); } //在规定时间内且该线程未被中断,尝试获取锁,获得成功则返回true,否则返回false。 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } //释放锁。如果该线程是锁的持有者,则count减1,直到count为0,锁成功释放。 若该线程不是锁的持有者,则抛出异常。 public void unlock() { sync.release(1); } //返回当前锁的Condition实例,这个后面会讲 public Condition newCondition() { return sync.newCondition(); } //返回当前线程持有锁的数量 public int getHoldCount() { return sync.getHoldCount(); } //判断该锁是否被该线程持有 public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } ······还有几个就不写了
参考资料:
来源:https://www.cnblogs.com/fruitknife/p/9703112.html