[TOC]
**多进程好多线程都有死锁的问题**
## 一 死锁现象
所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,
### 死锁案例-科学家吃面问题
~~~
import time
from threading import Thread,Lock
def eat1(name,fork_lock,noodle_lock):
fork_lock.acquire() #拿叉子锁
print('%s拿到叉子了'%name)
noodle_lock.acquire() #拿面条锁
print('%s拿到面条了' % name)
print('%s吃面'%name)
noodle_lock.release() #释放面条锁
fork_lock.release() #释放叉子锁
def eat2(name,fork_lock,noodle_lock):
noodle_lock.acquire()
print('%s拿到面条了' % name)
time.sleep(1)
fork_lock.acquire()
print('%s拿到叉子了' % name)
print('%s吃面'%name)
fork_lock.release()
noodle_lock.release()
fork_lock = Lock()
noodle_lock = Lock()
Thread(target=eat1,args=('alex',fork_lock,noodle_lock)).start()
Thread(target=eat2,args=('wusir',fork_lock,noodle_lock)).start()
~~~
**执行效果**
~~~
alex拿到叉子了
alex拿到面条了
alex吃面
wusir拿到面条了
yuan拿到叉子了 #出现死锁,整个程序阻塞住
~~~
## 二 递归锁
解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。
这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。
### 递归锁解决吃面问题
~~~
import time
from threading import Thread,RLock
def eat1(name,fork_lock,noodle_lock):
fork_lock.acquire()
print('%s拿到叉子了'%name)
noodle_lock.acquire()
print('%s拿到面条了' % name)
print('%s吃面'%name)
noodle_lock.release()
fork_lock.release()
def eat2(name,fork_lock,noodle_lock):
noodle_lock.acquire()
print('%s拿到面条了' % name)
time.sleep(1)
fork_lock.acquire()
print('%s拿到叉子了' % name)
print('%s吃面'%name)
fork_lock.release()
noodle_lock.release()
fork_lock =noodle_lock = RLock()
#一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,
#这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
Thread(target=eat1,args=('alex',fork_lock,noodle_lock)).start()
Thread(target=eat2,args=('wusir',fork_lock,noodle_lock)).start()
Thread(target=eat1,args=('yuan',fork_lock,noodle_lock)).start()
~~~
执行结果:
```
alex拿到叉子了
alex拿到面条了
alex吃面
wusir拿到面条了
wusir拿到叉子了
wusir吃面
yuan拿到叉子了
yuan拿到面条了
yuan吃面
Process finished with exit code 0
```
## 互斥锁和递归锁的区别
互斥锁在同一个线程中连续acquire一次以上就会死锁
递归锁在同一个线程中可以连续的acquire多次而不发生死锁
* 普遍说法 :
递归锁可以代替互斥锁来解决死锁现象
* 实际上 :
递归锁的解决死锁实际上是牺牲了时间和空间的
**死锁从本质上来讲是一种逻辑错**
**递归锁没有从根本上解决死锁问题**