可中断锁

可中断锁:顾名思义,就是可以相应中断的锁。

在Java中,synchronized就不是可中断锁,而Lock是可中断锁。

如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。

在前面演示lockInterruptibly()的用法时已经体现了Lock的可中断性。

线程在调用lock方法来获得另一个线程所持有的锁的时候,很可能发生阻塞。应该更加谨慎地申请锁。tryLock方法试图申请一个锁,在成功获得锁后返回true,否则,立即返回false,而且线程可以立即离开去做其他事。

可以调用tryLock时,使用超时参数。
lock方法不能被中断。如果一个线程在等待获得一个锁时被中断,中断线程在获得锁之前一直处于阻塞状态。如果出现死锁,那么,lock方法就无法终止。

API介绍:
Lock接口
1、tryLock
boolean tryLock()
仅在调用时锁为空闲状态才获取该锁。  
如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。

此方法的典型使用语句如下:

      Lock lock = ...;      if (lock.tryLock()) {          try {
              // manipulate protected state
          } finally {
              lock.unlock();
          }
      } else {
          // perform alternative actions
      }12345678910

此用法可确保如果获取了锁,则会释放锁,如果未获取锁,则不会试图将其释放。

返回:
如果获取了锁,则返回 true;否则返回 false。

2、tryLock
boolean tryLock(long time,
               TimeUnit unit)
               throws InterruptedException
如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。  
如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态:

锁由当前线程获得;或者  
其他某个线程中断当前线程,并且支持对锁获取的中断;或者  
已超过指定的等待时间  
如果获得了锁,则返回值 true。

如果当前线程:

在进入此方法时已经设置了该线程的中断状态;或者  
在获取锁时被中断,并且支持对锁获取的中断,  
则将抛出 InterruptedException,并会清除当前线程的已中断状态。  
如果超过了指定的等待时间,则将返回值 false。如果 time 小于等于 0,该方法将完全不等待。

实现注意事项

在某些实现中可能无法中断锁获取,即使可能,该操作的开销也很大。程序员应该知道可能会发生这种情况。在这种情况下,该实现应该对此进行记录。

相对于普通方法返回而言,实现可能更喜欢响应某个中断,或者报告出现超时情况。

Lock 实现可能可以检测锁的错误用法,例如,某个调用可能导致死锁,在特定的环境中可能抛出(未经检查的)异常。该 Lock 实现必须对环境和异常类型进行记录。

参数:
time - 等待锁的最长时间
unit - time 参数的时间单位  
返回:
如果获得了锁,则返回 true;如果在获取锁前超过了等待时间,则返回 false  
抛出:  
InterruptedException - 如果在获取锁时,当前线程被中断(并且支持对锁获取的中断)

3、lockInterruptibly
void lockInterruptibly()
                      throws InterruptedException
如果当前线程未被中断,则获取锁。  
如果锁可用,则获取锁,并立即返回。

如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:

锁由当前线程获得;或者  
其他某个线程中断当前线程,并且支持对锁获取的中断。  
如果当前线程:

在进入此方法时已经设置了该线程的中断状态;或者  
在获取锁时被中断,并且支持对锁获取的中断,  
则将抛出 InterruptedException,并清除当前线程的已中断状态。  
实现注意事项

在某些实现中可能无法中断锁获取,即使可能,该操作的开销也很大。程序员应该知道可能会发生这种情况。在这种情况下,该实现应该对此进行记录。

相对于普通方法返回而言,实现可能更喜欢响应某个中断。

Lock 实现可能可以检测锁的错误用法,例如,某个调用可能导致死锁,在特定的环境中可能抛出(未经检查的)异常。该 Lock 实现必须对环境和异常类型进行记录。

抛出:  
InterruptedException - 如果在获取锁时,当前线程被中断(并且支持对锁获取的中断)。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
:``` import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; public class InterruptibleLockDemo { private static ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { try { // 在5秒内尝试获取,如果获取不到则中断线程 lock.tryLock(5, TimeUnit.SECONDS); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + " is interrupted."); return; } System.out.println(Thread.currentThread().getName() + " got the lock."); lock.unlock(); } }, "ThreadA"); Thread t2 = new Thread(new Runnable() { @Override public void run() { lock.lock(); System.out.println(Thread.currentThread().getName() + " got the lock."); lock.unlock(); } }, "ThreadB"); // 先启动t2,让其获取到 t2.start(); // 等待1秒后再启动t1尝试获取 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } t1.start(); // 等待t1结束 try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } // 中断t1 t1.interrupt(); } } ``` 在这个例子中,我们先启动了一个线程 t2,让其获取到。然后等待1秒后再启动一个线程 t1,让其在5秒内尝试获取。由于 t2 已经持有,t1 尝试获取会被阻塞。3秒后,我们中断 t1,它会抛出 InterruptedException,并且不会执行后面的释放的操作。最终,我们看到 t1 没有获取到,而 t2 成功获取到并释放了

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值