用通知-等待机制优化锁等待问题

news2024/9/22 11:27:25

破坏占用且等待就可以避免死锁产生,以上一节中的循环等待代码来看:

// 一次性申请转出账户和转入账户,直到成功
while(!actr.apply(this, target))
 ;

如果apply()操作耗时非常端,而且并发冲突量不大时,这个方案是不错的,因为这种场景下,循环上几次或者几十次就可以一次性获取锁,执行业务。但是如果apply()操作耗时长,或者并发冲突量很大的时候,循环等待就可能循环上万次才能获取锁,会导致CPU使用率升高,影响环境的问题。

这种场景,更好的解决方案是:如果线程要求的条件不满足,则线程阻塞自己,进入等待状态,在满足线程要求的条件后,通知等待的线程重新执行。

完整的等待-通知机制:线程首先获取互斥锁,当线程要求的条件不满足时,释放互斥锁,进入等待状态;当要求的条件满足时,通知等待的线程,重新获取互斥锁。

用synchronized实现等待-通知机制

在Java语言中,使用synchronized配合wait()、notify()、notifyAll()这三个方法就可以轻松实现。

image

如图,左边一个等待队列,同一时刻,只允许一个线程进入synchronized保护的临界区,当有一个线程进入临界区后,其他线程只能进入图中左边的队列等待,这个等待队列和互斥锁是一对一的关系,每个互斥锁都有自己独立的等待队列。

进入临界区后,由于不满足部分条件,需要进入等待状态,Java对象的wait()方法就能满足这个需求,当调用wait()方法后,当前线程就会被阻塞,并且进入右侧的等待队列,这个等待队列也是互斥锁的等待队列。线程在进入右侧等待队列的同时,会释放持有的互斥锁,线程释放后,其他线程就有机会获得锁,进入临界区。

当线程条件满足时,通知等待的线程,可以使用Java对象的notify()和notifyAll()方法,通知等待队列中的线程,条件曾经满足过,可以再次尝试获取锁,并判断条件是否满足。

对之前的代码进行优化

 while(条件不满足) {
   wait();
 }
class Allocator {
 private List<Object> als;
 // 一次性申请所有资源
 synchronized void apply(
   Object from, Object to){
   // 经典写法
   while(als.contains(from) ||
        als.contains(to)){
     try{
       wait();
     }catch(Exception e){
     }   
   } 
   als.add(from);
   als.add(to);  
 }
 // 归还资源
 synchronized void free(
   Object from, Object to){
   als.remove(from);
   als.remove(to);
   notifyAll();
 }
}

用notifyAll()而没有使用notify(),是因为notify()会随机通知等待队列中的一个线程,而notifyAll()会通知等待队列中所有的线程,第一反应是同一时间只有一个线程进入临界区,用notify()就可以了,实际上notify()可能导致某些线程永远不会被通知到。

学习来源:极客时间 《Java 并发编程实战》学习笔记 Day04

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

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

相关文章

新春限定:新红包封面项目

新春限定&#xff1a;红包封面项目项目系统流量系统项目系统 去看一下“微信红包封面”的微信指数&#xff1a; 这个指数越大&#xff0c;代表市场越大。 入局这个生意&#xff0c;不需要门槛。 注册红包封面网站&#xff1a;http://ozqxsct.hsenzy.com/ 要用夸克、Edge、…

正确清理mysql-bin

1. 背景 机器磁盘满导致mysql连接不上&#xff0c;删除部分日志&#xff0c;错误将mysql-bin.0050* 都删除&#xff0c;重启mysql失败 $ service mysqld start Starting MySQL.......... ERROR! The server quit without updating PID file (/data/mysqldata/gzqc249-243-214…

Linux diffstat命令

Linux diffstat命令根据diff的比较结果&#xff0c;显示统计数字。diffstat读取diff的输出结果&#xff0c;然后统计各文件的插入&#xff0c;删除&#xff0c;修改等差异计量。语法diff [-wV][-n <文件名长度>][-p <文件名长度>]参数&#xff1a;-n<文件名长度…

WPF 笔记1——分析WPF程序文件

看B站刘铁猛老师视频学习WPF 1、创建WPF项目 打开VS&#xff0c;新建一个WPF项目&#xff0c;文件结构如下图&#xff1a; 通常&#xff0c; xxx.xaml、 xxx.xaml.cs是一组文件&#xff0c;用来定义一个名称是xxx的类。 2、xxx.xaml文件剖析 <Window x:Class"WpfAp…

红黑树作业

简介本文是为操作系统作业而实现的红黑树源码。作业题目选题为&#xff1a;“(3)红黑树(rbtree)数据结构介绍及其在Linux内核中的应用(结合内核源码进行分析&#xff0c;内核版本号不低于2.6.0)”。因为网上太多红黑树原理的讲解了&#xff0c;不需要再去讲解原理&#xff0c;所…

Tokitsukaze and a+b=n (hard)(差分)

C-Tokitsukaze and abn (hard)_2023牛客寒假算法基础集训营2 (nowcoder.com) 题目描述 Tokitsukaze有一个整数n&#xff0c;以及m个区间[L, R]。 她想知道有多少种选法&#xff0c;满足:从m个区间中选择两个区间[L; R],[Lj;,R](i≠j)&#xff0c;并从第一个区间选择一个整数a(…

redis为什么需要主从复制?

为什么要有主从复制&#xff0c;使redis具有高可用性&#xff01; 多机情况下主从复制 同步文件和同步命令 同步文件 客户端发送命令 slaveof 给从服务器从服务器发送 sync 命令给主服务器&#xff0c;主服务器收到以后&#xff0c;会执行bgsave命令 生成rdb文件&#xff0c;同…

2.3总线仲裁

文章目录一、引子二、总线仲裁三、集中仲裁方式1.链式查询方式&#xff08;1&#xff09;介绍&#xff08;2&#xff09;过程&#xff08;3&#xff09;特点&#xff08;4&#xff09;优缺点①优点②缺点2.计数器查询方式&#xff08;1&#xff09;介绍&#xff08;2&#xff0…

在线支付系列【4】支付安全之数字签名

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录信息摘要摘要算法数据完整性数字签名签名流程验签流程实现代码信息摘要 信息摘要就是一段数据的特征信息&#xff0c;当数据发生了改变&#xff0c;信息摘要也会发生改变&#xff0c;发送方会将…

12月知识小报|线上问题的抽丝剥茧与一锤定音

海恩法则是德国飞机涡轮机的发明者帕布斯海恩提出的一个在航空界关于飞行安全的法则。每一起严重事故的背后&#xff0c;必然有29次轻微事故和300起未遂先兆以及1000起事故隐患。作为开发者&#xff0c;安全生产是我们底线&#xff0c;敬畏每一行代码&#xff0c;挖掘每一个故障…

LINUX学习之文件基本属性(二)

查看文件属性 Linux 系统是一种典型的多用户系统&#xff0c;不同的用户处于不同的地位并拥有不同的权限。在 Linux 系统中&#xff0c;通常使用 chown 命令来修改文件或目录的所有者&#xff0c;chmod 命令则用于设置用户的权限。 chown (change owner) &#xff1a;用于修改…

Linux下的进程通信之system V共享内存

目录 使用system V共享内存进行进程间通信&#xff1a; 获取共享内存shmget 将共享内存关联到进程 去关联共享内存 删除共享内存 简易模拟实现server和client之间的通信&#xff1a; 服务端代码&#xff1a; 客户端代码&#xff1a; 共享内存的特点&#xff1a; 其他…

solrCloud一:zookeeper集群搭建

SolrCloud是基于Solr和Zookeeper的分布式搜索方案&#xff0c;它的主要思想是使用Zookeeper作为集群的配置信息中心。SolrCloud是Solr的一种分布式部署方式 &#xff0c;当索引越来越大时&#xff0c;一个单一的系统无法满足空间和查询效率上的要求&#xff0c;这个时候往往需要…

SpringCloud(11):Hystrix请求合并

1 简介 如图&#xff0c;多个客户端发送请求调用(消费者)项目中的findOne方法&#xff0c;这时候在这个项目中的线程池中会发申请与请求数量相同的线程数&#xff0c;对EurekaServiceProvider(服务提供者)的getUserById方法发起调用&#xff0c;每个线程都要调用一次&#xff0…

圆满落幕!56 人参加,龙蜥社区技术委员会、运营委员会会议顺利完成

1 月 13 日&#xff0c;龙蜥社区分别召开了第 10 次技术委员会会议和第 14 次运营委员会会议&#xff0c;来自 21 家理事单位的委员代表出席。两个会上分别总结和回顾了龙蜥社区 2022 年度整体技术和运营发展情况&#xff0c;就社区产品、重要技术决策、社区治理、2023 年度运营…

塔望3W消费战略全案丨火出天际的预制菜,能否拯救开饭焦虑?

2022年6月塔望咨询开设塔望食品大健康消费研究院&#xff08;简称塔望食研院&#xff09;栏目&#xff0c;塔望食研院以“为食品行业品牌高质量发展赋能”为理念&#xff0c;将不定期发布食品大健康行业研究、消费研究报告。塔望食研院致力于结合外部数据、消费调研数据、企业内…

Web(九)

Web服务器软件Tomcat web服务器软件&#xff1a; 服务器&#xff1a;安装了服务器软件的计算机 服务器软件&#xff1a;接收用户的请求&#xff0c;处理请求&#xff0c;做出响应 web服务器软件&#xff1a;接收用户的请求&#xff0c;处理请求&#xff0c;做出响应。 在…

说话人识别损失函数的PyTorch实现与代码解读

概述 说话人识别中的损失函数分为基于多类别分类的损失函数&#xff0c;和端到端的损失函数&#xff08;也叫基于度量学习的损失函数&#xff09;&#xff0c;关于这些损失函数的理论部分&#xff0c;可参考说话人识别中的损失函数本文主要关注这些损失函数的实现&#xff0c;…

SQL 分组条件深入剖析

问题在 stackoverflow 网站上看到这样一个 SQL 分组条件的需求&#xff0c;需求看似挺简单&#xff0c;但能把 SQL 写正确对于新手来说也不容易&#xff0c;我们拿过来深入剖析一下&#xff0c;数据如下&#xff1a;需求是查找只有Ready 状态的设备。解答自然思路&#xff1a;按…

寅辞旧岁,卯定常虹丨ASKO洗碗机“净”护新春团圆时刻

农历新年是一年中最重要的节日&#xff0c;但过去三年的特殊时光阻碍了很多人的归乡之行&#xff0c;如今当阴霾逐渐散去&#xff0c;必然会引来大规模的新年归乡潮&#xff0c;奔赴一个久违的团圆年。美馔佳宴是新春佳节的永恒命题&#xff0c;新年家里少不了亲友的光临&#…