前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ReentrantLock 锁

ReentrantLock 锁

作者头像
Qwe7
发布2022-08-06 15:57:04
2440
发布2022-08-06 15:57:04
举报
文章被收录于专栏:网络收集

ReentrantLock 锁

实现 Lock 接口,使用时需导入 import java.util.concurrent.locks.*;

实现功能和 synchronized 关键字类似。但 synchronized 关键字是在 JVM 层面实现的,而 ReenTrantLock 是在 JDK 层面实现的。需要手动调用 lock 和 unlock 方法配合 try/finally 语句块来完成。

代码语言:javascript
复制
public class ReentrantLockTest {
    // 创建锁对象
    static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        for(int i = 0; i < 5; i++){
            new Thread(new MyThread()).start();
        }
    }

    static class MyThread implements Runnable {
        @Override
        public void run() {                                   
            try {
                // 加锁,通常在 try 语句里完成
                lock.lock();
                Thread.sleep(500);
                System.out.println(Thread.currentThread().getName() + "excute");
            } catch (InterruptedException e) {}
            finally{
                // 解锁,必须在 finally 语句里完成
                lock.unlock();    
            }                      
            }
        }
    }
}Copy to clipboardErrorCopied

ReenTrantLock 比 synchronized 增加了一些高级功能,主要有以下三点:

实现等待中断

调用 lockInterruptibly 方法上锁,线程中断标志置为 true 时会抛出 InterruptedException 异常并释放锁。防止线程因为无法获得锁而一直等待,常用来从外部破坏线程死锁。

代码语言:javascript
复制
public class ThreadDemo {
    // 创建锁对象
    static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new MyThread(),"thread1");
        Thread t2 = new Thread(new MyThread(),"thread2");
        t1.start();
        t2.start();
        Thread.sleep(500);
        // 提前中断线程
        t2.interrupt();                                      
    }

    static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "begin");
            try {
                // 加可中断锁
                lock.lockInterruptibly();                    
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "out");
            } finally{
                try{
                    lock.unlock();
                } catch(IllegalMonitorStateException e) {}  
                System.out.println(Thread.currentThread().getName() + "end");
            }
        }
    }
}Copy to clipboardErrorCopied

调用 tryLock 方法上锁,可以从线程内部破坏死锁,可以更好地解决死锁问题。

  • 传入时间参数设定等待锁的时间,超时没有获得锁则中止。
  • 无参则返回锁申请的结果:true表示获取锁成功,false表示获取锁失败。
代码语言:javascript
复制
public class ThreadDemo {
    // 创建锁对象
    static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new MyThread(),"thread1");
        Thread t2 = new Thread(new MyThread(),"thread2");
        t1.start();
        t2.start();                                  
    }

    static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "begin");
            try {
                // 加锁失败直接退出
                if(!lock.tryLock()) {                         
                    System.out.println(Thread.currentThread().getName() + "out");
                    return;
                }                  
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally{
                try{
                    lock.unlock();
                } catch(IllegalMonitorStateException e) {}
                System.out.println(Thread.currentThread().getName() + "end");
            }
        }
    }
}Copy to clipboardErrorCopied

实现公平锁

允许先等待的线程先获取锁,防止线程因无法获得锁而一直等待。但由于性能优势,默认情况下仍使用非公平锁。在构造锁对象时添加参数 true 即可实现。

代码语言:javascript
复制
import java.util.concurrent.locks.*;

public class ReentrantLockTest {
    // 创建锁对象,且声明为公平锁
    static Lock lock = new ReentrantLock(true);

    public static void main(String[] args) throws InterruptedException {
        for(int i = 0; i < 5; i++){
            new Thread(new MyThread()).start();
        }
    }

    static class MyThread implements Runnable {
        @Override
        public void run() {
            lock.lock();                                     
            try {
                Thread.sleep(500);
                System.out.println(Thread.currentThread().getName() + "excute");
            } catch (InterruptedException e) {}
            lock.unlock();                                 
            }
        }
    }
}Copy to clipboardErrorCopied

选择性通知

ReentrantLock 对象可以创建一个或多个 Condition 对象,实现线程间的等待通知机制。比 synchronized 关键字 使用 wait/notify 方法更为简便和易用。

线程获得 Lock 锁之后便可调用 Condition 接口的 await 方法释放锁并等待,直到有其他线程调用 Condition 的 signal 方法唤醒线程。通过设置多个 condition 对象,多个线程等待不同的 condition 对象,可以实现选择性地叫醒线程。

代码语言:javascript
复制
public class ThreadDemo {

    static ReentrantLock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();

    public static void main(String[] args) throws InterruptedException {
        lock.lock();
        new Thread(new MyThread()).start();
        System.out.println("主线程等待通知");
        try {
            condition.await();
        } finally {
            lock.unlock();
        }
        System.out.println("主线程恢复运行");
    }

    static class MyThread implements Runnable {
        @Override
        public void run() {
            lock.lock();
            try {
                condition.signal();
                System.out.println("子线程通知");
            } finally {
                lock.unlock();
            }
        }
    }
}

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ReentrantLock 锁
    • 实现等待中断
      • 实现公平锁
        • 选择性通知
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档