1、可重入锁是可以中断的,如果发生了死锁,可以中断程序

 //如下程序出现死锁,不去kill jvm无法解决死锁
public class Uninterruptible {
public static void main(String[] args) throws InterruptedException {
final Object o1 = new Object(); final Object o2 = new Object();
Thread t1 = new Thread() {
public void run() {
try {
synchronized(o1) {
Thread.sleep(1000);
synchronized(o2) {}
}
} catch (InterruptedException e) { System.out.println("t1 interrupted"); }
}
};
Thread t2 = new Thread() {
public void run() {
try {
synchronized(o2) {
Thread.sleep(1000);
synchronized(o1) {}
}
} catch (InterruptedException e) { System.out.println("t2 interrupted"); }
}
};
t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt();
t2.interrupt();
t1.join();
t2.join();
}
}

然后是解决方法:We can reimplement our threads using Reentrant-Lock instead of intrinsic locks, and we can use its lockInterruptibly() method

Thread A先取得lock,Thread B无法取得lock进入block状态,可以透过发出interrupt方式唤醒Thread B,这就是和lock的区别

  • lock():若lock被thread A取得,thread B会进入block状态,直到取得lock。
  • tryLock():若当下不能取得lock,thread就会放弃。
  • lockInterruptibly():跟lock()情況一下,但是thread B可以透过interrupt被唤醒处理InterruptedException。
 final ReentrantLock l1 = new ReentrantLock();
final ReentrantLock l2 = new ReentrantLock();
Thread t1 = new Thread() {
public void run() {
try {
➤ l1.lockInterruptibly();
Thread.sleep(1000);
➤ l2.lockInterruptibly();
} catch (InterruptedException e) { System.out.println("t1 interrupted"); }
}
};
Thread t2 = new Thread() {
public void run() {
try {
➤ l2.lockInterruptibly();
Thread.sleep(1000);
➤ l1.lockInterruptibly();
} catch (InterruptedException e) { System.out.println("t2 interrupted"); }
}
}; t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt(); //当执行到时,线程会捕获InterruptedException程序会结束
t2.interrupt();
t1.join();
t2.join();
}

2、设置锁超时时间

  • tryLock():若线程一定时间不能取得lock,thread就会放弃。
 public class LockTimeOut{
private ReentrantLock leftChopstick, rightChopstick;
public void method(){
Thread.sleep(random.nextInt(1000)); // Think for a while
leftChopstick.lock();
try {
➤ if (rightChopstick.tryLock(1000, TimeUnit.MILLISECONDS)) {
// Got the right chopstick
………
} }

  

说明:Instead of using lock(), this code uses tryLock(), which times out if it fails to acquire the lock

3、条件变量,所谓的  Condition: await()/signal(),可以实现每个关注自己的信号量,每个人有每个人的信号量

When you use Condition: await()/signal() you can distinguish which object or group of objects/threads get a specific signal.

Here is a short example where some threads, the producers, will get the isEmpty signal while the consumers will get the isFull signal:

这里会有两个信号量,生产者和消费这关注的信号量是不一样的,每个人有每个人关注的信号量

private volatile boolean usedData = true;//mutex for data
private final Lock lock = new ReentrantLock();
private final Condition isEmpty = lock.newCondition();//生产者关心 isEmpty信号量
private final Condition isFull = lock.newCondition(); public void setData(int data) throws InterruptedException {
lock.lock();
try {
while(!usedData) {//wait for data to be used如果数据为没有消费,那么就会阻塞到 isEmpty信号量,生产者等待这个空信号量
isEmpty.await();
}
this.data = data;
isFull.signal();//broadcast that the data is now full. 释放 isFull满这个信号量
usedData = false;//tell others I created new data.
}finally {
lock.unlock();//interrupt or not, release lock
}
} public void getData() throws InterruptedException{
lock.lock();
try {
while(usedData) {//usedData is lingo for empty 这里都必须是循环,因为 从await()这个函数 退出阻塞说明条件可能满足,不是一定满足
isFull.await();
}
isEmpty.signal();//tell the producers to produce some more.
usedData = true;//tell others I have used the data.
}finally {//interrupted or not, always release lock
lock.unlock();
}
}

然后注意信号量和 条件是不一样的东西

if the condition is not true, it calls await(), which atomically unlocks the lock and blocks on the condition variable.

When another thread calls signal() or signalAll() to indicate that the condition might now be true, await() unblocks and automatically reacquires the lock. An important point is that when await() returns, it only indicates that the condition might be true. This is why await() is called within a loop—we need to go back,recheck whether the condition is true, and potentially block on await() again if necessary.

 ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (!<<condition is true>>) //如果条件不满足
condition.await();
<<use shared resources>>
} finally { lock.unlock(); }

然后是具体实例

 private void think() throws InterruptedException {
table.lock();
try {
eating = false;
left.condition.signal();//释放条件变量
right.condition.signal();//释放条件变量
} finally { table.unlock(); }
Thread.sleep(1000);
}
private void eat() throws InterruptedException {
table.lock();
try {
13 while (left.eating || right.eating)
14 condition.await();
eating = true;
} finally { table.unlock(); }
Thread.sleep(1000);
}

java ReentrantLock可重入锁功能的更多相关文章

  1. java ReentrantLock可重入锁的使用场景

    摘要 从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果发现该操作已经在执行中则不再执行(有状态执行) a.用在定时任务时,如果任务执行时间可能超过下次 ...

  2. JUC 一 ReentrantLock 可重入锁

    java.util.concurrent.locks ReentrantLock即可重入锁,实现了Lock和Serializable接口 ReentrantLock和synchronized都是可重入 ...

  3. ReenTrantLock可重入锁(和synchronized的区别)总结

    ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...

  4. ReentrantLock可重入锁的理解和源码简单分析

    import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * @author ...

  5. ReenTrantLock可重入锁和synchronized的区别

    ReenTrantLock可重入锁和synchronized的区别 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入 ...

  6. Java中可重入锁ReentrantLock原理剖析

    本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQue ...

  7. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  8. ReentrantLock——可重入锁的实现原理

    一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQueuedSynchronizer的简单原理,然后通过分析ReentrantLock的lo ...

  9. ReentrantLock可重入锁——源码详解

    开始这篇博客之前,博主默认大家都是看过AQS源码的~什么居然没看过猛戳下方 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础 全网最详细的Abstra ...

随机推荐

  1. windows 2003 企业版 下载地址+序列号

    迅雷地址: thunder://QUFodHRwOi8vcy5zYWZlNS5jb20vV2luZG93c1NlcnZlcjIwMDNTUDJFbnRlcnByaXNlRWRpdGlvbi5pc29a ...

  2. 使用python做科学计算

    这里总结一个guide,主要针对刚开始做数据挖掘和数据分析的同学 说道统计分析工具你一定想到像excel,spss,sas,matlab以及R语言.R语言是这里面比较火的,它的强项是强大的绘图功能以及 ...

  3. OD附加功能分析

    OD版本:OllyICE v1.10   在从文件菜单选择附加后,OD会在注册一个窗口类后,先创建一个0x138大小的进程表; 再是CreateWindowExA 创建窗口;   00478013 l ...

  4. UVA136 求第1500个丑数

    枚举大范围数据..暴力检查题目条件 #include <iostream> #include <cstdio> #include <vector> #include ...

  5. DOM、Window对象操作

    一.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档:对象是指文档中每个元素:模型是指抽象化的东西. 一.基本语法: 数据类型(字符串,小数,整数,布尔,时间) var, v ...

  6. Activity之间传递数据的方式及常见问题总结

    Activity之间传递数据一般通过以下几种方式实现: 1. 通过intent传递数据 2. 通过Application 3. 使用单例 4. 静态成员变量.(可以考虑 WeakReferences) ...

  7. LoadRunner11录制APP脚本(2)

    通过安卓模拟器实现LoadRunner11录制APP脚本 http://www.51testing.com/html/24/15110424-3686857.html http://www.51tes ...

  8. Liferay 6.2 改造系列之二十四:修改liferay密码的加密方式

    为了便于后期与Cas集成过程中使用数据库用户的方便,将liferay密码的加密方式改为SHA. 在/portal-master/portal-impl/src/portal.properties配置文 ...

  9. 30分钟LINQ教程(转)

    在说LINQ之前必须先说说几个重要的C#语言特性 一:与LINQ有关的语言特性 1.隐式类型 (1)源起 在隐式类型出现之前, 我们在声明一个变量的时候, 总是要为一个变量指定他的类型 甚至在fore ...

  10. Android利用Fiddler进行网络数据抓包

    最新最准确内容建议直接访问原文:Android利用Fiddler进行网络数据抓包 主要介绍Android及IPhone手机上如何进行网络数据抓包,比如我们想抓某个应用(微博.微信.墨迹天气)的网络通信 ...