在学习python多任务的时候遇到了这样一个奇怪的问题。
两个线程并行start,睡眠时间设定为1秒,下面是具体代码。
import multiprocessing
import time
def task1(count):
for i in range(count):
print('task1-', i+1)
time.sleep(1)
def task2(content, count):
for i in range(count):
print(content, '-', i+1)
time.sleep(1)
if __name__ == '__main__':
# 利用args元组传参
# p1 = multiprocessing.Process(target=task1, args=(5,))
# p2 = multiprocessing.Process(target=task2, args=('Python', 5))
# 利用kwargs字典传参
p1 = multiprocessing.Process(target=task1, kwargs={'count': 5})
p2 = multiprocessing.Process(target=task2, kwargs={'content': 'Python', 'count': 5})
p1.start()
p2.start()
运行之后得到了如下结果:
可以清楚的看到其中第二次和第五次循环打印时两个线程内容错乱交替在了一起,由于正在练习带参数的多线程任务,期初我以为是传入args或者kwargs类型出现了问题,于是将两种传参方式都写出来还是出现同样的错误。
但是多次重复运行后会发现还是有许多正常打印的结果:
至此我不得不思考是不是python的多线程相对于java,c++等其他语言来说不那么安全,导致了线程不安全,我们知道进程是需要分配线程来执行任务的,因此是不是在上面的案例错乱的两次循环中出现了两个进程抢占同一个线程执行任务的情况?
在网上查了很多发现有人说时因为python2的多线程是不安全的,会造成打印错乱,到了python3就没这种问题了…可事实是我就是python3出现的问题,终于经过许多身边高人的询问指导后我找到了问题所在。
因为python的多线程是伪多线程,由于全局锁的存在。
GIL全局解释锁,python在运行过程中只有一个线程执行字节码。python虚拟机本身是一个单线程的东西,在全局锁的时候会导致其他启动的线程都被暂停掉挂起,然后资源分配在当前的线程上面。就是比如你创建五个线程,但是正在运行的时钟只有一个,即使你的cpu有四个八个核心,同理进程也是这个原因。但是对于普通的线程,比如pthread或者是windows linux上面的这些来说的话就能够默认用到每个线程都在一个cpu上运行,达到并行的效果。