2020年6月5日 / 343次阅读 / Last Modified 2020年6月5日
多线程
python多线程虽然有GIL管着,在IO密集型任务的时候,还是可以用的。本文给出一个很简单的线程不安全的示例,说明一个事情:凡是共享的资源,都要自己加锁控制,不要以为python的每一行脚本都是原子操作,虽然python自定的确定义了一些原子操作,但是不要去依赖,如果哪一天python解释器修改了内部机制,你的代码就会崩溃;对于共享资源,无论有几个修改线程,加把锁更安全。
线程不安全一例:
from threading import Thread, Lock
number = 0
def target():
global number
for _ in range(1000000):
number += 1
thread_01 = Thread(target=target)
thread_02 = Thread(target=target)
thread_01.start()
thread_02.start()
thread_01.join()
thread_02.join()
print(number)
两个线程,并发对一个全局变量进行+1操作,我们预期的结果是2000000,但是不是,每一次运行都不是,而且还不一样:
D:\py>python thread_not_safe.py
1391219
D:\py>python thread_not_safe.py
1241460
D:\py>python thread_not_safe.py
1210578
D:\py>python thread_not_safe.py
1221867
D:\py>python thread_not_safe.py
1136912
正确的代码应该是这样的:
from threading import Thread, Lock
number = 0
mutex = Lock()
def target():
global number
for _ in range(1000000):
mutex.acquire()
number += 1
mutex.release()
thread_01 = Thread(target=target)
thread_02 = Thread(target=target)
thread_01.start()
thread_02.start()
thread_01.join()
thread_02.join()
print(number)
这样每次运行代码得到的结果都是2000000!
-- EOF --
本文链接:https://www.pynote.net/archives/2047
《线程不安全一例》有5条留言
前一篇:time模块中的计时器
后一篇:python的原子操作
©Copyright 麦新杰 Since 2019 Python笔记
关于+1操作的bytecode:
[ ]真正引起数据冲突的,不是读,而是写! [ ]
原因说明:多个线程同时读取时,有可能读取到同一个 number 值,读取两次,却只加了一次,最终导致自增的次数小于预期。 [ ]
因此,其实有一种情况是不需要mutex的:只有一个线程在更新,而其它线程只是读取。 [ ]
When in doubt, use a mutex! [ ]