zoukankan      html  css  js  c++  java
  • java ReentrantLock可重入锁功能

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

     1 //如下程序出现死锁,不去kill jvm无法解决死锁
     2 public class Uninterruptible {
     3 public static void main(String[] args) throws InterruptedException {
     4 final Object o1 = new Object(); final Object o2 = new Object();
     5 Thread t1 = new Thread() {
     6 public void run() {
     7 try {
     8 synchronized(o1) {
     9 Thread.sleep(1000);
    10 synchronized(o2) {}
    11 }
    12 } catch (InterruptedException e) { System.out.println("t1 interrupted"); }
    13 }
    14 };
    15 Thread t2 = new Thread() {
    16 public void run() {
    17 try {
    18 synchronized(o2) {
    19 Thread.sleep(1000);
    20 synchronized(o1) {}
    21 }
    22 } catch (InterruptedException e) { System.out.println("t2 interrupted"); }
    23 }
    24 };
    25 t1.start();
    26 t2.start();
    27 Thread.sleep(2000);
    28 t1.interrupt(); 
    29 t2.interrupt();
    30 t1.join(); 
    31 t2.join();
    32 }
    33 }

    然后是解决方法: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。
     1 final ReentrantLock l1 = new ReentrantLock();
     2 final ReentrantLock l2 = new ReentrantLock();
     3 Thread t1 = new Thread() {
     4 public void run() {
     5 try {
     6 ➤ l1.lockInterruptibly();
     7 Thread.sleep(1000);
     8 ➤ l2.lockInterruptibly();
     9 } catch (InterruptedException e) { System.out.println("t1 interrupted"); }
    10 }
    11 };
    12 Thread t2 = new Thread() {
    13 public void run() {
    14 try {
    15 ➤ l2.lockInterruptibly();
    16 Thread.sleep(1000);
    17 ➤ l1.lockInterruptibly();
    18 } catch (InterruptedException e) { System.out.println("t2 interrupted"); }
    19 }
    20 };
    21 
    22 
    23 t1.start();
    24 t2.start();
    25 Thread.sleep(2000);
    26 t1.interrupt(); //当执行到时,线程会捕获InterruptedException程序会结束
    27 t2.interrupt();
    28 t1.join(); 
    29 t2.join();
    30 }

    2、设置锁超时时间

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

      

    说明: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.

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

    然后是具体实例

     1 private void think() throws InterruptedException {
     2 table.lock();
     3 try {
     4 eating = false;
     5 left.condition.signal();//释放条件变量
     6 right.condition.signal();//释放条件变量
     7 } finally { table.unlock(); }
     8 Thread.sleep(1000);
     9 }
    10 private void eat() throws InterruptedException {
    11 table.lock();
    12 try {
    13 while (left.eating || right.eating)
    14 condition.await();
    15 eating = true;
    16 } finally { table.unlock(); }
    17 Thread.sleep(1000);
    18 }
    我当记事本用的
  • 相关阅读:
    微信浏览器内 h5 直接唤醒 app 之 微信开放标签 wx-open-launch-app
    HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何结合createJS应用box2d.js
    HTML5之2D物理引擎 Box2D for javascript Games 系列 第三部分之创建图腾破坏者的关卡
    HTML5之2D物理引擎 Box2D for javascript Games 系列 第二部分
    HTML5之2D物理引擎 Box2D for javascript Games 系列 第一部分
    写给“有钱大爷”、”美工殿下”、“前端文艺青年”的微信HTML5页面设计建议
    微信 JS-SDK Demo “分享信息设置” API 及数字签名生成方法(NodeJS版本)更新时间(2020-10-29)
    NodeJS让前端与后端更友好的分手
    “榕树下·那年”移动app ( hybrid ) 开发总结
    如何在移动端app中应用字体图标icon fonts
  • 原文地址:https://www.cnblogs.com/amazement/p/4867809.html
Copyright © 2011-2022 走看看