Python基础–互斥锁与死锁
在线程同时对一个全局变量写的时候,会造成资源竞争的现象,这个时候就引入到一个互斥锁
的概念.
当直接运行下面的程序的时候会出现两者的和不为200000的现象.这个就属于资源竞争.请看下先的实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import threading import time # 定义全局变量 g_num = 0
# 循环一次给全局变量加1 def sum_num1(): for i in range(1000000): global g_num g_num += 1 print("sum1:", g_num)
# 循环一次给全局变量加1 def sum_num2(): for i in range(1000000): global g_num g_num += 1 print("sum2:", g_num)
if __name__ == '__main__': # 创建两个线程 first_thread = threading.Thread(target=sum_num1) second_thread = threading.Thread(target=sum_num2) # 启动线程 first_thread.start() second_thread.start() time.sleep(2) print(g_num)
|
互斥锁解决资源竞争
- 互斥锁的模板
1 2 3 4 5 6 7
| # 创建锁 # lock1 是指定的对象的名字,直接使用对象的名字进行调用 lock1 = threading.Lock() # 加锁 lock1.acquire() # 释放锁 lock1.release()
|
完整的解决资源竞争的互斥锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| # 具体原理这边就不做深究了,因为牵涉到了cpu运算和内存交互. # 代码上锁是直接添加到数据计算的层面上 # 如果直接加到函数的前后,直接 import threading import time # 定义全局变量 g_num = 0
# 创建全局互斥锁 lock = threading.Lock()
# 循环一次给全局变量加1 def sum_num1(): for i in range(1000000): global g_num lock.acquire() g_num += 1 lock.release() print("sum1:", g_num)
# 循环一次给全局变量加1 def sum_num2(): for i in range(1000000): global g_num lock.acquire() g_num += 1 lock.release() print("sum2:", g_num)
if __name__ == '__main__': # 创建两个线程 first_thread = threading.Thread(target=sum_num1) second_thread = threading.Thread(target=sum_num2) # 启动线程 first_thread.start() second_thread.start() # sleep方法是因为计算时间不大确定,所以需要等一会 time.sleep(2) print(g_num)
|
join方法处理互斥锁(不推荐)
join 方法是相当于把多线程修改成单线程,依次执行,这样虽然也能避免资源竞争的问题,但是相对来说处理速度较慢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import threading import time # 定义全局变量 g_num = 0
# 循环一次给全局变量加1 def sum_num1(): for i in range(1000000): global g_num g_num += 1 print("sum1:", g_num)
# 循环一次给全局变量加1 def sum_num2(): for i in range(1000000): global g_num g_num += 1 print("sum2:", g_num)
if __name__ == '__main__': # 创建两个线程 first_thread = threading.Thread(target=sum_num1) second_thread = threading.Thread(target=sum_num2) # 启动线程 first_thread.start() first_thread.join() second_thread.start() second_thread.join() print(g_num)
|
死锁
死锁是一件非常可怕的事情,一直处在堵塞状态.而造成死锁的原因就是因为使用了互斥锁
只是直接上锁,但是却没有==释放锁==操作,具体的代码这里就不详细在写了,上面的代码中有解锁的部分,只需要直接删除任意一个解锁的操作即可实现.
==建议大家在使用互斥锁的时候可以直接上锁和解锁一起写,就是成对的出现,最后调整解锁的位置即可,以免出现死锁,从而导致程序堵塞的现象==