32.Common Concurrency Problems


32. Common Concurrency Problems

32.1 What Types Of Bugs Exist?

  • 并发中有哪些类型的bug?大致分为两种:non-deadlock bugsdeadlock bugs

32.2 Non-Deadlock Bugs

  • 主要又分为两类:atomicity violationorder violation
  • atomicity violation

可能出现的Bug:

解决办法:

  • order violation

可能出现的bug:

解决方法:

  • Non-Deadlock Bugs: Summary

97%的非死锁bug都是原子性和同步的问题,一般通过lock可以解决。

32.3 Deadlock Bugs

  • 死锁,当不同进程循环等待资源时,就会造成死锁。

假设线程1占有lock1,线程2占有lock2,那么就造成了死锁。

  • 死锁产生的条件:

Mutual exclusion:线程要对想访问的资源申请互斥访问,比如加锁。

Hold and wait:当线程在等待其他资源时,保持自己已经申请到的资源。

No preemption:不能强制线程放弃已占有的资源。

Circular wait:存在一条循环等待链,其中已经占有部分资源的线程在等待其他线程。

四个条件必须同时满足才能产生死锁。也就是说只要破坏其中一个条件就可以避免死锁。下面康康如何破坏这四个条件。

  • Prevention

Circular wait

可以通过固定资源的访问顺序来破坏循环等待条件。比如在上面那个栗子中,可以规定线程必须先申请lock1再申请lock2,这样就可以避免死锁。但是这种做法往往不现实,因为你要知道系统中所有要用到的资源,并且不方便新增资源。

Hold and wait

可以通过让线程一次性申请完所需的所有资源后再往下进行,像这样:

但是这种做法会降低系统的并发性。

No preemption

可以通过当线程由于申请不到其他资源而等待时,释放掉其已经占有的资源,像这样:

Mutual exclusion

可以通过不使用lock的方式来申请对资源的访问,比如使用compareAndSwap:

  • Deadlock Avoidance via Scheduling

除了死锁预防,还可以死锁避免。死锁避免需要知道运行过程中的线程可能需要申请哪些lock,并合理安排对这些lock的调度。比如银行家算法,虽然可以有效避免死锁,但是应用场景比较局限,并且会限制系统的并发性。

  • Detect and Recover

最后是检测和恢复,也就是说允许系统产生死锁,但是产生死锁后通过一定的手段对死锁进行恢复。比如通过检测进程资源图中是否存在循环等待来判断死锁,或者一个线程等待资源时间过长就判断发生死锁等;然后再通过强制释放某个进程的资源来打破死锁。

32.4 Summary

  • 这一章介绍了并发问题可能存在Bug,分为非死锁问题和死锁问题。非死锁问题主要是原子性和顺序性的问题;死锁问题主要是如何预防、避免、检测并恢复。

文章作者: foursevenlove
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 foursevenlove !
 上一篇
DRL-1.Overview DRL-1.Overview
DRL-1.Overview1.RL Basics1.1 Terminology State:当前环境的状态空间 Action:Agent当前可以采取的动作空间 Policy $\pi$ :policy函数$\pi:(s,a) ->
下一篇 
31.Semaphores 31.Semaphores
31. Semaphores 前面已经学习了使用lock和condition varivable来实现并发,这一节学习semaphore信号量。有了semaphore,就只有统一的原语操作了,可以用semaphore来实现lock和cond
  目录