前言
上节课我们分享了Python多线程的基础语法,以及GIL的相关概念,这节课我们重点讲解一个知识点,就是多线程的数据安全问题。
数据安全问题
我们首先来举一个例子,这里定义两个函数,一个是自加1,一个时自减1,按正常的逻辑来说,最后这个值应该是0,但是程序每次运行的结果都不一样,有正数,也有负数。
import threading
num = 0
def add():
global num
for i in range(10000000):
num += 1
def sub():
global num
for i in range(10000000):
num -= 1
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=sub)
t1.start()
t2.start()
t1.join()
t2.join()
print(num)
这就是多线程的数据安全的问题,我简单解释一下,因为线程会在两个函数中来回切换,好比在add函数中,刚准备加1时,程序被打断,跳到了sub函数中继续执行,这就会导致num值的改变。
我们举一个现实中的案例,很多人抢一张火车票,如果是多线程,当一个人在抢票时,突然切换到另外一个人买票,他买到了,然后又返回到第一个人,他这边还是显示的还有一张票,但其实后台已经没票了。
锁
这时我们就可以手动加锁来解决这样的问题。
import threading
num = 0
lock = threading.Lock()
def add():
lock.acquire()
global num
for i in range(10000000):
num += 1
lock.release()
def sub():
lock.acquire()
global num
for i in range(10000000):
num -= 1
lock.release()
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=sub)
t1.start()
t2.start()
t1.join()
t2.join()
print(num)
acquire函数就是申请锁,release就是释放锁,这样就能保证数据的安全。
今天的分享就到这了,我们下期再见~
网友评论