操作系统导论第32章——常见并发问题

本文探讨了并发编程中的非死锁(97%的问题所在)和死锁缺陷,包括违反原子性和顺序的问题,以及死锁的四个必要条件。解决死锁的方法包括避免循环等待、持有并等待、非抢占和互斥等问题,涉及全序锁、trylock、无锁编程等技术。此外,还讨论了通过调度和死锁检测来预防和解决死锁的策略。
摘要由CSDN通过智能技术生成

1. 非死锁缺陷

非死锁缺陷占了并发问题的大多数(97%)

1.1 违反原子性缺陷

含义:代码段本意是原子的,但是子执行过程并没有强制实现原子性

解决办法:加锁

1.2 违反顺序缺陷

含义:A应该在B之前执行,但是实际上却不是这个顺序

解决办法:条件变量(实际上还要用到锁和状态的变量)

2. 死锁缺陷

含义:当线程1持有锁L1,正在等待另外一个锁L2,线程2持有锁L2,却在等待锁L1释放,死锁产生。

为什么死锁容易发生?

  • 大型代码库中,组件之间有复杂的依赖
  • 封装(不知道细节导致的)

死锁产生的条件:

  • 互斥:线程对需要的资源进行互斥访问
  • 持有并等待:线程持有了资源,又在等待其他资源
  • 非抢占:如锁不能被抢占
  • 循环等待:线程之间存在环路

解决办法如下:

2.1 针对循环等待

获得锁的时候提供全序或者偏序

技巧:通过锁的地址来强制锁的顺序

2.2 针对持有并等待

原子地强锁,相当于增加一个全局锁来控制锁的请求

这种方式不适用封装,而且降低并发度

2.3 针对非抢占

可以使用trylock(),尝试获得锁,如果锁被占用,则释放持有资源,等待一段时间

问题1:可能出现活锁(两个线程一直重复该方式,又同时强锁失败);解决办法:随机等待一个时间

问题2:封装导致恢复到未持有锁之前的状态比较困难

2.4 针对互斥

无锁编程,利用硬件指令,比如原子的比较并交换指令(比较变量是否等于期待值,如果是则赋给它新值,并返回1,如果不等于返回0,什么都不做)

困难:实现比较困难

2.5 通过调度避免死锁

基本原理:让可能出现死锁是线程顺序执行

缺陷:影响性能

2.6 恢复并检查

死锁检测器定期检查(通过构建资源图),检查到死锁,系统重启

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值