死锁问题,4个必要条件+避免死锁

目录

引入

死锁

概念

示例

多把锁

单锁

4个必要条件 

用途 


引入

我们用加锁的方式保证了多个线程访问临界资源时,不会出现数据紊乱的问题

但是,锁的引入,会导致出现其他的问题

死锁

概念

  • 在多线程或多进程的并发环境中,两个或多个进程或线程被永久阻塞,因为它们在等待对方释放资源,而自己却不释放已经占有的资源
  • 进程或线程无法继续执行,而无法自行解除阻塞

示例

多把锁

一个线程可以申请多把锁:

  • 线程A申请了a锁,线程B申请了b锁
  • 但在两个线程释放锁之前,线程A又需要b锁(也就是需要访问b锁范围内的临界区代码),那么A就会等待b锁的释放
  • 但是此时,如果线程B需要用a锁,就会形成死锁了
  • 因为a锁还正在被线程A持有,线程B需要等待a锁的释放
  • 于是,这两个线程就互相等待对方释放锁,但都处于挂起状态,而锁是无法自己释放的,所以他俩只能一直这么等下去

单锁

如果只需要一把锁,也可能会出现死锁问题(当然,这是特殊情况)

  • 如果一个线程已经申请了a锁,在释放锁之前,它又不小心申请了锁 / 把释放锁的函数名unlock写成了lock,就会形成死锁
  • 因为锁已经被持有(虽然这个人是自己),但是lock函数的第一句就是将al赋为0,所以自己持有的状态并不影响lock的执行
  • 他依然会用内存中mutex的0和al的0交换,然后判断失败被挂起
  • 挂起后,线程带走自己的上下文数据,也就是al中的0
  • 这样,锁就丢失了,线程永远也无法等待到锁

4个必要条件 

互斥条件

  • 一个资源每次只能被一个执行流使用
  • (这是基础条件,我们只有使用了互斥锁,才会出现死锁问题)

请求与保持条件

  • 一个执行流因请求资源而阻塞时,对已获得的资源保持不放
  • (也就是既要又要,他不会放弃自己的,又会向别人索要)

不剥夺条件

  • 一个执行流已获得的资源,在末使用完之前,不能强行剥夺
  • (他虽然向别人索要,但只是一种请求,不会也不能强制拿取)

循环等待条件

  • ​​​​​​​若干执行流之间形成一种头尾相接的循环等待资源的关系
  • 也就是说,申请资源的方向要形成环

用途 

因为是必要条件,所以只要这四个条件之一不满足,即可避免死锁问题

比如:

  • 我们只有在必要时才使用锁,并且要将锁的范围尽可能的缩小
  • 在申请别人的资源不成功若干次后,可以考虑先释放掉自己的锁(万一对方就是在等这个锁呢)
  • 尽量在一个锁范围内完成对共享资源的处理,避免出现多个锁 / 严格控制每个线程申请锁的顺序

你可能感兴趣的:(linux,linux)