管程-并发编程的利器

3 篇文章 0 订阅

引言

  • 相信大家一定知道信号量。在上学的时候,老师讲到操作系统,一般都会说信号量;并会列举出信号量解决了哪些问题,例如生产者消费者的同步问题、科学家就餐等问题,解决这些问题就会使用到pv信号量来解决多线程间的同步问题;由多线程间的同步,我们又会想到线程间的通信常用的六种方式为:信号量、匿名管道、命名管道、socket、共享内存空间、消息队列;通过这六种方式,我们就可以实现线程间的通信。我们会发现,只要是线程间的问题,大部分都可以使用信号量解决,而我们本文所说的管程就是和信号量等价的,信号量能够解决的问题,使用管程也能够解决。那有些人就会问:既然管程能解决的,使用信号量就能够解决,并且我们都学习过信号量,为什么还要再学管程?在这里,我的理解是:信号量的使用门槛是比较高的,稍有不慎就会出现问题,没有一个固定的思考范式,而管程就不一样了,我们可以把管程抽象成一个小区,这个小区只有一个出入口,在人多的时候,我们需要排队刷门禁卡进入小区;在这里,我们的临界区就是小区,加锁的位置就是小区刷门禁卡进来的位置,解锁的位置就是刷门禁卡出去的位置。结果上述的抽象,我们就可以形成一种意识:涉及到并发代码的部分就是小区,我们需要在这部分代码前后设置好加解锁的位置。

正题

  • 在java1.5之前,java里面只有synchronized、wait、notify、notifyAll等方式,这些方式实际上用的就是管程。我的理解是:synchronized包起来的代码块部分就是小区,wait就是相当于你的朋友让你去小区外面等他,notify是你通知某一个人可以进入小区,notifyAll是你用大喇叭告诉所有的人此时可以进小区。进入小区之后,还会进入某一幢楼,这个时候要满足一定的条件才可以进入,如果不满足,就会让你等着,等到满足条件之后,才可以允许你进入。
  • 管程通常有三种模型:Hasen模型、Hoare模型、MESA模型。这三种模型只是在通知方式上有所不同,例如t1线程因为不满足某些条件开始阻塞,t2线程执行了一些步骤之后导致t1线程所需要的条件满足了,这个时候就需要通知t1线程。

Hasen模型

  • 要求t2线程在结束的时候通知t1线程,相当于notify()、notifyAll()写在最后面;适用于生产者-消费者场景

Hoare模型

  • 要求t2在t1满足条件后,立即通知t1,t2开始阻塞直到t1运行结束,相当于调用join(),相比较于Hasen模型,多了一步等待t2线程被唤醒继续执行;适用于主线程依赖子线程执行结果的场景。

MESA模型

  • t2通知完t1线程之后,并不会立即进入阻塞状态,而是会继续执行,t1进入到入口处的等待队列中,等待再次进入、再次判断条件是否满足。相比较于Hoare模型,此处没有t2再次被唤醒的过程,只是t1执行的时候,条件不一定满足了,所以一般需要循环判断条件变量是否满足;类似于notify()、notifyAll()在t1需要的条件变量满足之后可以直接调用,不需要严格限定位置,比Hasen更具灵活性,t1响应的实时性比Hoare模型低。
  • java只要使用的就是MESA模型。管程模型图大致如下在这里插入图片描述

总结

通常我们会把条件变量的判断写成一个循环,因为阻塞线程再次被唤醒时,条件变量可能又不满足了,一般是这样的:

while(条件变量不满足) {
	wait();
}

如果我们写成

if (条件变量不满足) {
	wait();
}

当我们的线程被唤醒时,就不会再次进行条件变量的判断,这个时候是有风险的,例如涉及到电商商品库存的时候,就会造成超卖。
一般的完整流程代码如下:

A {
	
	锁 lock;
	 方法 A () {
	 	
	 	// 加锁
	 	lock.lock();
	 	while (条件变量不满足) {
	 		wait();
		}
		// 通知代码,具体可根据自己的代码逻辑设置通知
		notify();
		// 逻辑代码
		lock.unlock();
	
	}
	
}

参考:
https://time.geekbang.org/column/article/86089
https://www.cnblogs.com/myworld7/p/12238796.html#_label4
https://blog.csdn.net/qq_33479841/article/details/126091931

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值