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

news/2023/6/6 23:21:08

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

// 一次性申请转出账户和转入账户,直到成功
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.exyb.cn/news/show-4558572.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

Computer Vision_Matlab (3)

1 Box Masks Ia imread (rooster.jpg); Ib imread (elephant.png); Ic imread (boxes.pgm); Ia im2gray (Ia); Ib im2gray (Ib); Ic im2gray (Ic); Ia im2double (Ia); Ib im2double (Ib); Ic im2double (Ic); figure(100), imagesc (Ic), colorbar; box5ones(5,5).

通过KNN算法使用电脑摄像头识别人脸

主要通过knn算法生成训练集,然后通过调用电脑摄像头进行人脸识别,废话不多说, 直接上代码! import math import os import pickle import re import face_recognition import cv2 import numpy as np from PIL import Image, ImageDraw, ImageFont from face_recognition.face…

python非线性可分支持向量机模型(实现iris分类)

内容&#xff1a; 非线性可分支持向量机模型 分别使用线性核﹑多项式核与高斯核对lris 数据集的2/3数据训练支持向量机&#xff0c;剩余1/3数据进行测试&#xff0c;计算正确率。 分别使用线性核、多项式核与高斯核对lris数据集的2/3数据训练支持向量机&#xff0c;剩…

根据缠论选择盘整股票或者期货合约

盘整是一个比较难易判断的技术形态&#xff0c;最近基于jqdatasdk研究了通过缠论来判断盘整的方法&#xff0c;感觉效果还可以。特此贡献再次&#xff0c;以便和大家一起探讨关于盘整的思路。 # 导入函数库 from jqdatasdk import *# 第三方函数库 import numpy as np import…

模拟退火+粒子群算法寻找最小值点

模拟退火粒子群算法寻找最小值点原理简述1 模拟退火2.粒子群算法求解最优化问题原理简述 1 模拟退火 和最简单的爬山法相比&#xff0c;模拟退火多了一个选择更差的解的概率&#xff0c;假设当前寻找到的解是xorgx_{org}xorg​&#xff0c;迭代一轮找到的新解为xnewx_{new}xn…

机器学习笔记(6)——线性回归逻辑回归

机器学习笔记&#xff08;6&#xff09;——线性回归&逻辑回归 本文部分图片来源网络或学术论文&#xff0c;文字部分来源网络与学术论文&#xff0c;仅供学习使用&#xff0c;持续修改完善中。 提示&#xff1a;配合西瓜书食用更佳~ 目录 机器学习笔记&#xff08;6&a…

VGG-Bayes图像识别,基于贝叶斯定理

贝叶斯法则 通常&#xff0c;事件A在事件B(发生)的条件下的概率&#xff0c;与事件B在事件A的条件下的概率是不一样的&#xff1b;然而&#xff0c;这两者是有确定的关系,贝叶斯法则就是这种关系的陈述。 作为一个规范的原理&#xff0c;贝叶斯法则对于所有概率的解释是有效的…

【机器学习】scikit-leran手写数字识别

目录 一、数据采集和标记 二、拆分训练集和测试集 三、选择模型开始训练 四、预测和评价 五、模型保存和加载 六、导入模型参数 中文社区&#xff1a;scikit-learn中文社区 一、数据采集和标记 数据集是重要且有时候是难得的 skleran自带了一些数据集&#xff1a;Sklea…