ReentrantLock 学习

Java接口Lock有三个实现类:ReentrantLock、ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock。Lock接口提供了比使用synchronized更广泛的锁操作。

ReentrantLock是一个可重入的互斥锁。重入的含义是:当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会被阻塞。但是如果某个线程试图获得一个已经由它自己持有的锁时,这个请求是会成功的。"重入"意味着获取锁的操作的粒度是"线程",而不是"调用"。重入的一种实现方式就是,为每个锁关联一个获取计数值和一个所有者线程。当计数值为0时,这个锁就被认为是没有被任何线程持有。当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取到的计数值置为1.如果同一个线程再次获取这个锁,计数值将被递增,而当线程退出同步代码块时,计数器会相应地递减。当计数值为0时,这个锁将被释放。

对于ReentrantLock锁将由最近成功获得锁,并且没有释放该锁的线程所拥有。当锁没有被另外一个线程所拥有时,调用lock的线程将会成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。

ReentrantLock基础API

  1. lock() 获取锁
    加锁,如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。
    如果当前线程之前已经获取到了该锁,则将保持计数加1,并且该方法立即返回。
    如果该锁已经被另一个线程保持,则该线程不可被调度(即当前线程处于阻塞状态)直到该线程获取到锁,并且在获取到锁后,将保持计数设置为1。

  2. unlock释放锁
    试图释放锁。如果当前线程是此锁所有者,则将保持计数减1。如果保持计数器现在为0,则释放该属锁。如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException。

private Lock lock = new ReentrantLock() ;
public void await() {
    try {
         lock.lock();//加锁
    }  finally {
        lock.unlock();//释放锁
    }
}
  1. trylock()
  • 仅在调用时锁未被另一个线程保持的情况下,才获取锁。

  • 如果该锁没有被另一个线程保持,并且立即返回 true 值,则将锁的保持计数设置为 1。即使已将此锁设置为使用公平排序策略,但是调用 tryLock() 仍将 立即获取锁(如果有可用的),而不管其他线程当前是否正在等待该锁。在某些情况下,此“闯入”行为可能很有用,即使它会打破公平性也如此。如果希望遵守此锁的公平设置,则使用 tryLock(0, TimeUnit.SECONDS) ,它几乎是等效的(也检测中断)。

  • 如果当前线程已经保持此锁,则将保持计数加 1,该方法将返回 true。

  • 如果锁被另一个线程保持,则此方法将立即返回 false 值。

  1. tryLock(long timeout, TimeUnit unit)
  • 如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁。

  • 为了使用公平的排序策略,如果其他线程已经获取此锁,并且还有其他线程都在等待该锁,则立刻不会获取一个可用的锁,而公平的和其他线程进行等待锁分配。这与trylock方法相反。如果想使用一个允许闯入公平锁的定时tryLock,那么可以将定时形式和不定时形式组合在一起使用:

if(lock.tryLock() || lock.tryLock(timeout,uniy)) {
//.....
}
  1. lockInterruptibly
    如果当前线程未被中断,则获取锁。
  • 如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。
  • 如果该线程已经保持此锁,则将保持计数加1,并且该方法立即返回。
  • 如果该锁已经被其他线程保持,则等待;等待过程中,如果被其他线程打算,则抛出InterrupterException,并且中断该线程。
  • 在具体业务里,因为此方法是一个显示中断点,所以要优先考虑响应中断,而不是响应锁的普通获取或重入获取。

总结

  • lock --> 无限锁 调用后一直阻塞直到获得锁。
  • tryLock --> 拿到锁就返回true,不然就返回false;带有时间限制的tryLock(),拿不到锁,就等待一段时间,超时返回false。与while配合,可以实现轮询锁。
  • lockInterruptibly --> 调用后如果没有获取到锁会一直阻塞,阻塞过程中会接受中断信号。

参考原文地址

  1. Java中Lock,tryLock,lockInterruptibly有什么区别?
posted @ 2017-11-22 20:08  做个有梦想的咸鱼  阅读(212)  评论(0编辑  收藏  举报