多任务-线程之资源竞争问题(互斥锁)
1.在多线程中,不可避免的一个问题,就是全局变量资源存在着被多个线程调用的问题,在调用的过程中就存在着资源竞争
2.这种资源竞争是如何产生的呢?
import threading import time g_num = 0 def work1(num): global g_num for i in range(num): g_num += 1 print("----in work1, g_num is %d---"%g_num) def work2(num): global g_num for i in range(num): g_num += 1 print("----in work2, g_num is %d---"%g_num) print("---线程创建之前g_num is %d---"%g_num) t1 = threading.Thread(target=work1, args=(100,)) t1.start() t2 = threading.Thread(target=work2, args=(100,)) t2.start() while len(threading.enumerate()) != 1: time.sleep(1) print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
如同上述代码,当线程执行次数有限时,全局资源不会发生大的变化,但是当高并发时,就会产生资源竞争问题,如以下代码:
import threading import time g_num = 0 def work1(num): global g_num for i in range(num): g_num += 1 print("----in work1, g_num is %d---"%g_num) def work2(num): global g_num for i in range(num): g_num += 1 print("----in work2, g_num is %d---"%g_num) print("---线程创建之前g_num is %d---"%g_num) t1 = threading.Thread(target=work1, args=(1000000,)) t1.start() t2 = threading.Thread(target=work2, args=(1000000,)) t2.start() while len(threading.enumerate()) != 1: time.sleep(1) print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
3.如何解决资源竞争问题?
当存在多个线程或者进程同时调用一个全局变量资源,并且会对它进行修改时,可以采用上锁这个方法,来解决资源竞争问题。
首先,需要了解什么叫做资源竞争?
资源竞争是指,一个全局变量资源在多个线程或者进程中被同时调用,造成该全局变量资源不断的被修改。
解决方法:采用全局变量锁,每当线程调用全局变量时,就将该资源上锁,不允许被调用,只有当调用结束后才打开锁,这里引入互斥锁,能够保证全局变量资源的安全。
互斥锁的两种状态:锁定/非锁定
解决资源竞争的好处:互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
4.互斥锁的定义
当在请求之前,资源没有被上锁,那么请求并不会堵塞;如果在请求之前,是被锁上的, 那么请求就处于一个堵塞状态,只有当前得锁被打开之后,才能在次上锁。
互斥锁的优缺点:
优点:确保了某段关键代码只能由一个线程从头到尾完整地执行
缺点:阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁
# 创建锁 mutex = threading.Lock() # 锁定 mutex.acquire() # 释放 mutex.release()