当前位置: 首页 > news >正文

java 并发编程-ReentrantLock

ReentrantLock

  • ReentrantLock与Synchronized
  • 工作原理
  • Condition

ReentrantLock与Synchronized

ReentrantLock是一种可重入的独占锁,相对于synchronized,ReentrantLock具备如下特点:

  1. 可中断
  2. 可以设置超时时间
  3. 可以设置为公平锁
  4. 支持多个条件变量
  5. 与synchronized一样,都支持可重入

在使用时要注意4个问题:

  1. 默认情况下ReentrantLock为非公平锁而非公平锁;
  2. 加锁次数和释放锁次数一定要保持一致,否则会导致线程阻塞或程序异常;
  3. 加锁操作一定要放在try代码之前,这样可以避免未加锁成功又释放锁的异常;
  4. 释放锁一定要放在finally中,否则会导致线程阻塞。

工作原理

当有线程调用lock方法的时候:如果线程获取到锁了,那么就会通过CAS的方式把AQS内部的state设置成为1。这个时候,当前线程就获取到锁了。只有首部的节点(head节点封装的线程)可以获取到锁。其他线程都会加入到这一个阻塞队列当中。如果是公平锁的话,当head节点释放锁之后,会优先唤醒head.next这一个节点对应的线程。如果是非公平锁,
允许新来的线程和head之后唤醒的线程通过cas竞争锁。

Condition

相当于synchronized中的wait()和notify()机制,通常与Lock接口(比如ReentrantLock)一起使用。调用Condition的await()和signal()方法,都必须在lock保护之内。

public class Main {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    public static volatile boolean flag = false;

    private void lockCondition() throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    System.out.println("t1线程抢到锁");
                    while (!flag) {
                        System.out.println("t1线程等待");
                        condition.await();
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    lock.unlock();
                    System.out.println("t1线程释放锁");
                }

                System.out.println("线程t1执行完成");

            }
        }, "t1").start();

        Thread.sleep(3000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    System.out.println("t2线程抢到锁");
                    flag = true;
                    condition.signal();
                } finally {
                    lock.unlock();
                    System.out.println("t2线程释放锁");
                }
                System.out.println("t2线程执行完成");
            }
        }, "t2").start();
    }

    public static void main(String[] args) throws InterruptedException {
        new Main().lockCondition();
    }
}

相关文章:

  • python识别扫描版PDF文件,获取扫描版PDF文件的文本内容
  • 二叉树搜索树与双向链表
  • hackmyvm-flossy
  • AWS用Glue读取S3文件上传数据到Redshift,再导出到Quicksight完整版,含VPC配置
  • Android: Fragment 的使用指南
  • 004 健身房个性化训练计划——金丹期(体态改善)
  • 汇编学习之《数据传输指令》
  • 远程装个Jupyter-AI协作笔记本,Jupyter容器镜像版本怎么选?安装部署教程
  • Rust 语言语法糖深度解析:优雅背后的编译器魔法
  • VoIP技术及其与UDP的关系详解
  • 五类线和六类线
  • 洛谷: P1825 [USACO11OPEN] Corn Maze S
  • 揭秘:父子组件之间的传递
  • Redis批量操作详解
  • Scala的基本语法(二)
  • Python第七章03:文件写入操作
  • JS判断对象是否为空的方法
  • 移动端六大语言速记:第4部分 - 数据结构
  • Linux环境下Ollama升级及Gemma3模型部署指南
  • 突发,国行 iPhone 17,支持 eSIM
  • wordpress如何设置头像/优化关键词排名提升
  • 东莞手机网站模板/舆情管理
  • 做美股的数据网站/网站设计公司模板
  • 代理网站有什么用/app用户量排名
  • 网站建设取得实效/廊坊seo排名收费
  • 建设网站内容的策划书/seo外链收录