一、互斥锁
1.实现原理及概念
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。
互斥锁为资源引入一个状态:锁定/非锁定。
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
2.互斥锁Lock函数介绍
acquire()——锁定资源
release() — 释放资源
3.例题:使用互斥锁解决200万次的计算问题。
源代码:
from threading import Thread
from threading import Lock
g_num = 0
#创建一个全局锁对象
lock= Lock()
def work1(num):
global g_num
lock.acquire()#加锁
for i in range(num):
g_num+=1
lock.release()#解锁
print("in work1-->",g_num)
def work2(num):
global g_num
lock.acquire()#加锁
for i in range (num):
g_num+=1
lock.release()#解锁
print("work2-->",g_num)
def main():
t1 = Thread(target=work1,args=(1000000,))
t2 = Thread(target=work2, args=(1000000,))
t1.start()
t2.start()
t2.join()
if __name__ == '__main__':
main()
print("main-->",g_num)
运行结果:
in work1--> 1000000
work2--> 2000000
main--> 2000000
二、死锁
1.死锁的概念
在许多应用中进程需要以独占的方式访问资源,当操作系统允许多个进程并发执行时可能会出现进程永远被阻塞现象,如两个进程分别等待对方所占的资源,于是两者都不能执行而处于永远等待状态,此现象称为死锁。
死锁通常被定义为:如果一个进程集合中的每个进程都在等待只能由此集合中的其他进程才能引发的事件,而无限期陷入僵持的局面称为死锁。
2.死锁产生的条件
(1).互斥条件
临界资源是独占资源,进程应互斥且排他的使用这些资源。
(2).占有和等待条件
进程在请求资源得不到满足而等待时,不释放已占有资源。
(3).不剥夺条件
又称不可抢占,已获资源只能由进程自愿释放,不允许被其他进程剥夺。
(4).循环等待
条件又称环路条件,存在循环等待链,其中,每个进程都在等待链中等待下一个进程所持有的资源,造成这组进程处于永远等待状态。
3.示例
源代码:
from threading import Lock
from threading import Thread
import time
lock1 = Lock()
lock2 = Lock()
def work1(num):
lock1.acquire()#lock1上锁
time.sleep(1)
print("in work1")
lock2.acquire() # lock2上锁
print("work1-----")
lock2.release()#lock2解锁
lock1.release()#lock1解锁
def work2(num):
lock2.acquire()#lock2加锁
print("in work2")
lock1.acquire()#lock1加锁
print("work1-----")
lock1.release()#lock1解锁
lock2.release()#lock2解锁
if __name__ == '__main__':
t1 = Thread(target=work1,args=(1000000,))
t2 = Thread(target=work2, args=(1000000,))
t1.start()
t2.start()
运行结果:
in work2
in work1