多线程和并发编程(3)—AQS和ReentrantLock实现的互斥锁

news2024/11/20 0:37:48

一、管程模型—MESA模型

管程是什么?

管程就是指管理共享变量,以及对共享变量的相关操作。

在管程的发展史上,先后出现过三种不同的管程模型,分别是Hasen模型、Hoare模型和MESA模型。现在正在广泛使用的是MESA模型。

MESA模型的核心是需要一个共享变量来表示共享资源的数量,同步等待队列中的线程请求到一个共享资源,相应共享变量要减一,一直到共享变量为0,则请求的线程阻塞在同步等待队列中,如果需要满足某些条件才能竞争共享资源,这些线程会阻塞在条件等待队列中,但条件满足后要么转移到同步等待队列中,要么直接占有共享资源。

MESA 管程模型

同步等待队列:竞争共享资源暂没竞争到的线程会阻塞在同步等待队列中。

条件等待队列:在竞争资源的过程中还未达到某个条件,会阻塞在条件等待队列中,其中需要达到的条件即用条件变量表示,当满足这个条件后就会转移到同步等待队列中。

二、AQS原理

在Java中针对管程有两种实现:(1)一种是基于Object的Monitor机制,用于synchronized内置锁的实现;(2)一种是抽象队列同步器AQS,用于JUC包下Lock锁机制的实现;以下重点介绍方案(2)中的AQS。

1.实现思路

对于被请求的共享变量如果是空闲的,则将请求共享资源的线程设置为工作线程并且将共享变量减一。对于被请求资源是被占用的情况,则将该线程阻塞起来放到双向同步等待队列中,等共享资源被释放再进行申请。

2.AQS的组成

  • 共享变量

AQS内部维护属性volatile int state ,其中state表示资源的可用状态,State三种访问方式:

  1. getState()
  2. setState()
  3. compareAndSetState()

AQS实现时主要实现以下几种方法:

  1. isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
  2. tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
  3. tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
  4. tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
  5. tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。
  • 同步队列

AQS的数据结构包括同步等待队列和条件等待队列,同步等待队列是一个双端队列CLH,每个队列元素为一个Node,Node中保存前驱后置节点、当前线程状态、当前线程以及下一个等待线程。每个Node通过获取和重置state参数来进行加锁操作。共享资源是否被占用是通过对state进行修改来实现的,当该共享资源被加锁后,就会修改state为1。条件等待队列是保存不满足条件的线程,每一个条件对于一个条件同步队列。

img

同步阻塞队列和条件阻塞队列在一定条件会相互转换,当条件阻塞队列满足条件的情况,就能转移到同步阻塞队列中。即同步阻塞队列中的线程只差竞争到锁,而条件阻塞队列中的线程还需要满足条件才能转移到同步阻塞队列。在Java中通过signal()或signalAll()将条件同步队列中的线程转移到同步等待队列。但不满足条件时,调用await()方法会将同步等待队列中线程转移到条件等待队列中。

  • 编程模型

常见的使用AQS的编程模式如下:

public class BlockedQueue<T>{
  final Lock lock = new ReentrantLock();
  final Condition condition1 = lock.newCondition();
  final Condition condition2 = lock.newCondition();
  //Boolean flag = true;

  // 入队
  void enq(T x) {
    lock.lock();
    try {
      while (!条件1){
        // 条件1不满足,进入1条件等待队列
        condition1.await();
      }  
      // ...
      //解锁前,唤醒条件2等待队列中线程
      condition2.signal();
    }finally {
      lock.unlock();
    }
  }
  // 出队
  void deq(){
    lock.lock();
    try {
      while (!条件2){
        // 条件2不满足,进入条件2等待队列
        condition2.await();
      }
      // ...
       //解锁前,唤醒条件1等待队列中线程
      condition1.signal();
    }finally {
      lock.unlock();
    }  
  }
}
  1. 申请一把Lock锁,即申请一个同步等待队列,每个线程进入业务处理前需要竞争锁资源,没有竞争上锁资源的线程放到同步等待队列中;
  2. 在获取锁之后,会进行条件判断,如果满足条件则会在持有该锁的条件下进行业务逻辑的处理,其他线程无法并发处理,如果没有满足条件则会进入到条件同步队列中,并且暂时释放锁,等待满足条件后再参与锁竞争;

三、ReentrantLock原理

ReentrantLock是实现AQS的悲观锁。初始化状态是state为0,当调用lock()方法时候会调用tryAcquire方法将其state设为1并且锁定,之后其他线程调用tryAcquire方法将会失败并加入到同步队列阻塞,直到该线程调用unlock()方法会将此锁释放,调用tryRelease方法释放锁,将state改为0,同时注意,该线程在释放该锁之前,可以重复获得此锁,所以ReentrantLock是可重入的。

ReentrantLock内部有三个内部类,包括抽象类Sync,和其实现类NonfairSync、FairSync,可以分别实现公平锁和非公平锁,对ReentrantLock的操作基本是对Sync的操作,Sync分为公平实现FairSync和非公平实现NonfairSync,他们都是继承AQS接口。

image-20230914205718458

ReentrantLock和synchronized的区别?

  • 相同点:

(1)synchronied和ReentrantLock都是可重入锁;

(2)synchronied是Java的关键字,是通过JVM对对象进行加Monitor锁操作实现的;而ReentrantLock通过JDK中的AQS接口来实现,提供多种加锁、解锁方法;

  • 不同点:

(1)特性:synchronied是非公平锁,ReentrantLock可以实现公平锁和非公平锁;ReentrantLock可以实现可中断、可重试、超时中断、多条件加锁机制;ReentrantLock可以实现等待多条件释放锁,总之ReentrantLock更加灵活、功能更强大;

(2)实现:Synchronized是JVM自动隐式加解锁,执行完成他会自动释放锁;ReentrantLock通过Lock()和unLock()实现手动加锁和取消加锁。

参考资料

  1. 管程(Moniter): 并发编程的基本心法:https://developer.aliyun.com/article/904581
  2. Java中的管程模型:https://segmentfault.com/a/1190000021557492

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1011183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日一博 - 反向代理、API 网关、负载均衡

文章目录 概述图解 概述 反向代理、API网关和负载均衡是在网络和服务器架构中用于不同目的的重要组件&#xff0c;它们有不同的功能和应用场景。以下是它们之间的区别和联系&#xff1a; 反向代理&#xff08;Reverse Proxy&#xff09;&#xff1a; 功能&#xff1a;反向代理…

Python 数据可视化:Seaborn 库的使用

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

u盘上面 安装 ubuntu 系统

u盘上面 安装 ubuntu 系统 下载 一个 Ubuntu 22.04.3 LTS 桌面版 https://ubuntu.com/download/desktop 找到一个U盘 参考文章&#xff1a; 把 Ubuntu 装到U盘里随身携带&#xff0c;并同时支持 BIOS 和 UEFI 启动 https://www.luogu.com.cn/blog/GGAutomaton/portable-ubu…

【数据结构】串的定义;存储结构;基本操作的实现

欢迎光~临~^_^ 目录 知识树 1、串的定义 2、串的存储结构 2.1顺序存储 静态存储 动态存储 2.2链式存储 2.3串的堆分配存储表示 3、串的基本操作 3.1求子串 3.2比较操作 3.3定位操作 4、C语言实现串的基本操作 知识树 1、串的定义 串是由零个或多个字符组成的…

Oracle,高斯创建自增序列

某些时候,需要获取到一个自增值 然后点击左下 Apply 也可以通过SQL语句执行 dual在Oracle中是张虚拟表&#xff0c;通常用于执行这样的查询 Oracle中查询语句: select 序列名.nextval from dual 在高斯数据库中:查询是 select my_sequence.nextval 不需要加form xxx 也…

微信小程序项目开发Day1

没接触过&#xff0c;直接看视频学习&#xff1a; 千锋教育微信小程序开发制作前端教程&#xff0c;零基础轻松入门玩转微信小程序_哔哩哔哩_bilibili千锋教育微信小程序开发制作前端教程&#xff0c;零基础轻松入门玩转微信小程序共计56条视频&#xff0c;包括&#xff1a;学…

20230914java面经记录

1.mq消息重复消费 2.mq消息堆积 3.如何实现消费的幂等性&#xff08;网站付款成功发货&#xff0c;使用mq做异步通知发货&#xff09; 4.log&#xff0c;debug&#xff0c;warn&#xff0c;error怎么用 5.java基础 6.效率问题 ArrayList a,b;HashSet c,d ;a,b,c,d各自有10…

GDB之修改字符串的值(十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

ESP32主板-MoonESP32

产品简介 Moon-ESP32主板&#xff0c;一款以双核芯片ESP32-E为主芯片的主控板&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;低功耗&#xff0c;板载LED指示灯&#xff0c;引出所有IO端口&#xff0c;并提供多个I2C端口、SPI端口、串行端口&#xff0c;方便连接&#xff0c;…

Claude 使用指南 | 可与GPT-4媲美的语言模型

本文全程干货&#xff0c;让你轻松使用上claude&#xff0c;这也是目前体验cluade的唯一途径&#xff01;废话不多说&#xff0c;直接上教程&#xff0c;cluade的能力不逊于GPT4&#xff0c;号称是ChatGPT4.0最强竞品。相对Chatgpt来说&#xff0c;Claude不仅是完全免费的&…

Prometheus存储容量估算和Prometheus联邦机制

Prometheus最受诟病的一点就是单机存储不好扩展。 Prometheus存储容量估算 根据老师的经验&#xff0c;每秒接收 80 万个数据点&#xff0c;算是一个比较健康的上限&#xff0c;因而一开始也无需用一台配置特别高的机器&#xff0c;随着数据量的增长&#xff0c;以后再升级硬…

图扑可视化图表组件之股票数据分析应用

股市是市场经济的必然产物&#xff0c;在一个国家的金融领域之中有着举足轻重的地位。在过去&#xff0c;人们对于市场走势的把握主要依赖于经验和直觉&#xff0c;往往容易受到主观因素的影响&#xff0c;导致决策上出现偏差。如今&#xff0c;通过数据可视化呈现&#xff0c;…

java 单元测试Junit

所谓单元测试&#xff0c;就是针对最小的功能单元&#xff0c;编写测试代码对其进行正确性测试。为了测试更加方便&#xff0c;有一些第三方的公司或者组织提供了很好用的测试框架&#xff0c;给开发者使用。这里介绍一种Junit测试框架。Junit是第三方公司开源出来的&#xff0…

JavaSE、JavaEE与Spring的概念和异同点剖析以及规范13 个分析

JavaSE、JavaEE与Spring的概念和异同点剖析以及规范13 个分析 目录概述需求&#xff1a; 设计思路实现思路分析1.什么是JavaSE2.是JavaEE3.什么是Spring 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&…

奇怪的3389端口~腾讯/百度云服务器镜像有问题?

新安装的腾讯云服务器&#xff0c;系统win2019&#xff0c;打开微软官方的TCPVIEW软件&#xff0c;只要稍等一会儿&#xff0c;就能看到来自国外的3389连接&#xff0c;处于established状态。 系统是新安装的&#xff0c;密码也是刚刚重置的复杂密码&#xff0c; 除了TCPVIEW没…

【CVPR2021】MVDNet论文阅读分析与总结

Challenge&#xff1a; 现有的目标检测器主要融合激光雷达和相机&#xff0c;通常提供丰富和冗余的视觉信息 利用最先进的成像雷达&#xff0c;其分辨率比RadarNet和LiRaNet中使用的分辨率要细得多&#xff0c;提出了一种有效的深度后期融合方法来结合雷达和激光雷达信号。 MV…

记录一个iOS使用陀螺仪3d效果的抖动问题

使用陀螺仪的时候&#xff0c;遇到一个问题&#xff0c;就是在拖动scrollView滚动的时候&#xff0c;3d效果的图片会抖动 实现3d效果的代码 - (void)updateWithGravityX:(double)gravityXgravityY:(double)gravityYgravityZ:(double)gravityZ {//因为在斜向上45度角的时候&am…

x86架构基础汇编知识

​ 通用寄存器 EAX 32位 函数返回值 AX 低16位 AH 高八位 AL 低八位 EBX 32位 ECX 32位 循环次数&#xff0c;this指针 EDX 32位 EBP 32位 栈底寄存器 ESP 32位 栈顶寄存器 ESI 源索引寄存器 EDI 目标索引寄存器 EIP 无法直接通过汇编操作 例子 mov al&#xff0c;0xff …

SQL SERVER 中无法删除table ‘biao’,因为它不存在或者您不具备相应的权限

删除table表 1.删除表示提示&#xff1a;SQL SERVER 中无法删除table ‘biao’&#xff0c;因为它不存在或者您不具备相应的权限。2.原因3.解决方法3.1 图3.2 图3.3 图3.4 图 1.删除表示提示&#xff1a;SQL SERVER 中无法删除table ‘biao’&#xff0c;因为它不存在或者您不具…

CRM软件系统如何实现客户的精细化管理

客户是企业的生命线&#xff0c;对客户进行精细化管理&#xff0c;是提高企业收益的关键。那么&#xff0c;如何进行客户管理&#xff1f;CRM系统可以实现精细化管理客户&#xff0c;提升客户的价值。下面我们就来详细说一说。 1、获取客户信息 CRM系统可以通过web表单、在线聊…