day47-线程-锁和死锁

#1、锁:防止多个线程同时读写某一块内存区域。
from threading import Thread
from threading import Lock
def func():
    global n
    lock.acquire()
    n -= 1        #每一个线程在操作数据之前先拿到钥匙,操作完成之后,释放钥匙。
    lock.release()

n = 10
t_list = []
lock = Lock()
for i in range(10):         #先开启所有子线程。
    t = Thread(target=func)
    t.start()
    t_list.append(t)
[t.join() for t in t_list] #最后才让主线程等待所有子线程结束而结束。这样才能实现异步操作。
print(n)

#2、RLock递归锁可以acquire多次和对应地release多次,Lock互斥锁只能acquire和release一次。
from threading import RLock
lock = RLock()
lock.acquire()
lock.acquire()
lock.acquire()
print('123')
lock.release()
lock.release()
lock.release()
#123

# 3、死锁:在不同的线程当中(eat和eat1),恰好要对两个数据(筷子和面)进行操作,使用Lock会产生死锁,数据不安全。
# 科学家吃面:吃面需要同时有筷子和面才能吃到,A吃完面把筷子和面放下让给B,B拿到筷子和面才能吃。
#            下面例子的结果是有人拿到面拿不到筷子,有人拿到筷子拿不到面,形成死锁。
from threading import Lock
from threading import Thread
import time
def eat(name):
    kz_lock.acquire()
    print('%s拿到筷子了'%name)
    m_lock.acquire()
    print('%s拿到面了'%name)
    print('%s可以吃面了'%name)
    time.sleep(1)#因为cpu调度是无序的,设置睡眠1秒是为了把问题更好的发掘出来,否则就算执行很多次,出现问题是小概率事件。
    m_lock.release()
    kz_lock.release()

def eat1(name):
    m_lock.acquire()
    print('%s拿到面了'%name)
    kz_lock.acquire()
    print('%s拿到筷子了'%name)
    print('%s可以吃面了'%name)
    kz_lock.release()
    m_lock.release()

kz_lock = Lock() #筷子锁
m_lock = Lock()  #面锁
t = Thread(target=eat,args=('tom',))
t.start()
t1 = Thread(target=eat1,args=('marry',))
t1.start()
t2 = Thread(target=eat,args=('jack',))
t2.start()
t3 = Thread(target=eat1,args=('alex',))
t3.start()
# tom拿到筷子了
# tom拿到面了
# tom可以吃面了
# jack拿到筷子了
# marry拿到面了

#Rlock解决死锁问题:
from threading import RLock
from threading import Thread
import time
def eat(name):
    kz_lock.acquire()
    print('%s拿到筷子了'%name)
    m_lock.acquire()
    print('%s拿到面了'%name)
    print('%s可以吃面了'%name)
    time.sleep(1)
    m_lock.release() #后面拿到的钥匙先还。
    kz_lock.release() #前面拿到的钥匙后还。

def eat1(name):
    m_lock.acquire()
    print('%s拿到面了'%name)
    kz_lock.acquire()
    print('%s拿到筷子了'%name)
    print('%s可以吃面了'%name)
    kz_lock.release()
    m_lock.release()

kz_lock = m_lock =  RLock() #筷子锁和面锁是同一把锁
t = Thread(target=eat,args=('tom',))
t.start()
t1 = Thread(target=eat1,args=('marry',))
t1.start()
t2 = Thread(target=eat,args=('jack',))
t2.start()
t3 = Thread(target=eat1,args=('alex',))
t3.start()
# tom拿到筷子了
# tom拿到面了
# tom可以吃面了
# marry拿到面了
# marry拿到筷子了
# marry可以吃面了
# jack拿到筷子了
# jack拿到面了
# jack可以吃面了
# alex拿到面了
# alex拿到筷子了
# alex可以吃面了


#Rlock解决死锁问题(更加简洁的写法):
from threading import RLock
from threading import Thread
def eat(name):
    lock.acquire()
    print('%s拿到筷子了'%name)
    lock.acquire()
    print('%s拿到面了'%name)
    print('%s可以吃面了'%name)
    lock.release()
    lock.release()

def eat1(name):
    lock.acquire()
    print('%s拿到面了'%name)
    lock.acquire()
    print('%s拿到筷子了'%name)
    print('%s可以吃面了'%name)
    lock.release()
    lock.release()

lock = RLock()
t = Thread(target=eat,args=('tom',))
t.start()
t1 = Thread(target=eat1,args=('marry',))
t1.start()
t2 = Thread(target=eat,args=('jack',))
t2.start()
t3 = Thread(target=eat1,args=('alex',))
t3.start()
原文地址:https://www.cnblogs.com/python-daxiong/p/12142779.html