0%

Python基础--互斥锁与死锁

python

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)

死锁

死锁是一件非常可怕的事情,一直处在堵塞状态.而造成死锁的原因就是因为使用了互斥锁只是直接上锁,但是却没有==释放锁==操作,具体的代码这里就不详细在写了,上面的代码中有解锁的部分,只需要直接删除任意一个解锁的操作即可实现.

==建议大家在使用互斥锁的时候可以直接上锁和解锁一起写,就是成对的出现,最后调整解锁的位置即可,以免出现死锁,从而导致程序堵塞的现象==