小编写这篇文章的一个主要目的,主要是来给大家去做一个详细解答,解答的内容是对python多线程的一个相关理解,包括其对多核cpu利用的一个详细解析,具体的内容,请各位读者仔细的进行阅读下文。


引言


我们经常听到"因为GIL的存在,python的多线程不能利用多核CPU",现在我们暂且不提GIL,python能不能利用多核cpu,今天我做了一个实验,代码很简单如下所示


  while 1:
  pass


没有运行这段代码前cpu状态

01.png

运行之后的状态


下面两张图是运行之后的状态,当然这只是两张比较有代表性的图,截图间隔有十几秒的样子

02.png

根据第一张图我们发现cpu1、cpu3的负载有明显增长,我们可以得出python线程是可以利用多核cpu的结论,之前一直以为python运行后会绑定cpu其中的一个核心现在看来并不是这个样子。第二张图就比较有意思了cpu2满载了,这又是为什么呢?


想来想去应该是linux中cpu对进程的亲和性导致的,这种亲和性是软性的并不是强制的,这也就解释了为什么第一张图中是多cpu在负载。


ok为了更直观的看出python线程能够利用多核cpu,我们改下代码,换一种方式再来看下


  import os
  while 1:
  print os.getpid()#输出进程号


运行代码结果

03.png

一目了然,线程的确在不同的核心上切换。


现在我们回过头看下那句经典的话"因为GIL的存在,python的多线程不能利用多核CPU",这句话很容易让人理解成GIL会让python在一个核心上运行,有了今天的例子我们再来重新理解这句话,GIL的存在让python在同一时刻只能有一个线程在运行,这毋庸置疑,但是它并没有给线程锁死或者说指定只能在某个cpu上运行,另外我需要说明一点的是GIL是与进程对应的,每个进程都有一个GIL。


python线程的执行流程理解


线程——>抢GIL——>CPU


这种执行流程导致了CPU密集型的多线程程序虽然能够利用多核cpu时跟单核cpu是差不多的,并且由于多个线程抢GIL这个环节导致运行效率<=单线程。


看到这可能会让人产生一种错觉,有了GIL后python是线程安全的,好像根本不需要线程锁,而实际情况是线程拿到CPU资源后并不是一直执行的,python解释器在执行了该线程100条字节码(注意是字节码不是代码)时会释放掉该线程的GIL,如果这时候没有加锁那么其他线程就可能修改该线程用到的资源;


遇到IO也会释放GIL


另外一个问题是遇到IO也会释放GIL,下面是这两种情况的例子


  import threading
  def m1():
  for _ in range(100000):
  a.append(1)
  def m2():
  for _ in range(100000):
  a.append(2)
  def check():
  检查a是否有序
  for i in range(len(a)):
  if i!=0:
  if a<i><a[i-1]:
  print a[i-1],a<i>
  return False
  return True
  t1=threading.Thread(target=m1)
  t2=threading.Thread(target=m2)
  t1.start()
  t2.start()
  t1.join()
  t2.join()
  print check()
  预期1111...22222...,截图显示跟预期的不同
  import threading
  text1='1'*10000
  text2='2'*10000
  def write(text):
  with open('test.txt','a')as f:
  f.write(text)
  def m1():
  write(text1)
  def m2():
  write(text2)
  t1=threading.Thread(target=m1)
  t2=threading.Thread(target=m2)
  t1.start()
  t2.start()
  t1.join()
  t2.join()


test.txt截图

04.png

最后结论是,因为GIL的存在,python的多线程虽然可以利用多核CPU,但并不能让多个核同时工作。


综上所述,上述内容就给大家介绍完毕,希望可以给大家带来帮助。

最近在考虑学习一门后端语言,在ruby和 python 直接犹豫,然后自己做了一些 比,希望能帮到有同样问题 你。 一、异同 比选择1、 Python 和ruby 相同点: 都强调语法简单,都具有更一般 表达方式。 python 是缩进,ruby是类basi...

ghnor

Python Process/Thread 概念整理

...------------------ 有句行话: “ python 线程 是鸡肋,推荐使用 进程!”为什么呢? 看两点: 1、GIL是什么?GIL 全称是Global Interpreter Lock(全局解释器锁),来源是 python 设计之初 考虑,为了数据安全所...

Youngs title: Python 中单 线程 线程 进程 效率 比实验date: 2016-09-30 07:05:47tags: [ 线程 , 进程, Python ]categories: [ Python ] meta: Python 线程 进程 Python 是运行在解释器中 语言,查找资料知道, python 中有一个全局锁(GIL)...

niceforbear