Python基础–互斥锁与死锁
在线程同时对一个全局变量写的时候,会造成资源竞争的现象,这个时候就引入到一个
互斥锁
的概念.
当直接运行下面的程序的时候会出现两者的和不为200000的现象.这个就属于资源竞争.请看下先的实例
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)
互斥锁解决资源竞争
- 互斥锁的模板
# 创建锁
# lock1 是指定的对象的名字,直接使用对象的名字进行调用
lock1 = threading.Lock()
# 加锁
lock1.acquire()
# 释放锁
lock1.release()
完整的解决资源竞争的互斥锁
# 具体原理这边就不做深究了,因为牵涉到了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 方法是相当于把多线程修改成单线程,依次执行,这样虽然也能避免资源竞争的问题,但是相对来说处理速度较慢
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)
死锁
死锁是一件非常可怕的事情,一直处在堵塞状态.而造成死锁的原因就是因为使用了
互斥锁
只是直接上锁,但是却没有释放锁操作,具体的代码这里就不详细在写了,上面的代码中有解锁的部分,只需要直接删除任意一个解锁的操作即可实现.
建议大家在使用互斥锁的时候可以直接上锁和解锁一起写,就是成对的出现,最后调整解锁的位置即可,以免出现死锁,从而导致程序堵塞的现象