Python中的多线程深入解析

进程

操作系统如何管理计算机的应用程序来分配资源的?
  • 进程:进程是竞争计算机资源的基本单位。每一个应用程序至少有一个进程
    单核CPU,永远只能够执行一个应用程序?
  • 在不同的应用程序之间切换
  • 同时pycharm,风暴英雄,QQ
    进程调度
  • 算法决定每个应用程序的挂起,或者是切换到另外一个进程
  • 操作系统原理中有详细讲解
  • 进程、线程相互切换的开销是非常大的,原因就是需要上下文需要保存,上下文频繁的保存加载所以需要的开销就是比较大的。

线程

线程和进程有什么区别?
  • 线程是进程的一部分,一个进程可以有一个线程,也可以有多个线程
  • 从资源的角度来看,进程管理CPU资源的话,粒度太大了,需要更小的单元来管理CPU的资源,需要一个更加灵活的小巧的机制来协调CPU资源的利用,这个就是线程,线程之间的切换资源消耗小很多
  • 线程和进程之间的分工不同,进程主要是用来分配资源(内存资源),而线程是用来利用CPU来执行代码的,线程本身不能够分配和拥有资源,但是线程可以访问资源
  • 线程是属于进程的,可以访问进程中的资源,这也是线程切换快速的一个原因

多线程

  • 想要代码运行的有效率,那么多线程是有必要的
  • 当我们写了代码的时候,不管代码多么的简单,都会有一个默认的线程来执行这个代码,这个默认的线程通常是主线程
import threading

print('i am qiyue’)
t = threading.current_thread()
print(t.getName())
# 主线程

执行结果:

i am qiyue
MainThread
  • 大多数情况下代码都是在主线程中执行的,但是其实我们还可以在主线程中启动其他的线程
# -*- coding: utf-8 -*-
import threading
def worker():
    print('i am thread')
    t = threading.current_thread()
    print(t.getName())
t = threading.current_thread()
print(t.getName())
new_t = threading.Thread(target=worker, name='qiyue-thread')
new_t.start()

执行结果:

MainThread
i am thread
qiyue-thread
  • 我们启动的线程是可以自定义名字的,还有一点值得注意,单线程是顺序执行的,但是一旦我们在主线程中启动了新的线程,那么这个线程的执行已经和主线程没有关系了。
多线程有什么优势和好处呢?
  • 充分的利用CPU的性能优势,从而加快代码的执行速度
  • 多线程的编程其实也是异步编程的一种形态
  • 还记得之前提到的一个特性吗?对于单核的CPU,同一时刻,只允许一个线程来执行代码,那么多线程的意义在什么地方呢,理论上是这样的,但是对于多核的CPU,比如4核的CPU,让A核处理主线程,其他的核处理新开的线程,多核的CPU完全是,有能力让不同的核去处理不同的线程,这个时候其实就是在并行的处理程序,其实这个就是多线程的意义。说到这个地方,我们看似都非常的美好,多核的CPU有非常的强大,但是,很遗憾的额告诉大家,我们的python是没有办法充分利用多核CPU优势的。
  • 一些有基础的同学可能听说过这么一句话,Python的多线程是鸡肋,那么这句话到底对不对呢?这就取决于你如何定义这个鸡肋了,在三国演义中,说所谓的鸡肋,食之无味,弃之可惜,当然,python的多线程还是有一定的意义的,如果没什么用,那还存在干啥呢,是吧。
  • 先来说一下为啥Python不能使用多核CPU,主要是因为,Python中存在一个GIL,全局解释器锁,在内存资源中,一个进程可以有多个线程,线程之间共享资源,这就有可能多个线程访问同一个资源,这就造成了线程有可能是不安全的,为了保证线程安全就出现了锁,一旦我们对某一个对象加锁之后,不管有多少个线程,只有拿到锁的线程才能对相关的变量进行操作。
  • 锁可以分为两类,一类是细粒度的锁,也就是程序员主动加的锁,一类是粗粒度的锁,解释器加的锁,比如,GIL,在python的解释器上,同一时刻只能有一个线程来执行,所以即使是多核的CPU也无能为力,在一定程度上保证了线程安全,比如有代码a+=1,这段代码到Python的解释器中会被翻译成bytecode,Python解释器会执行bytecode,这行代码可能被翻译成多段的bytecode,如果解释器正在执行这多段中的一段的时候,线程就被挂起了,然后切换到另外的线程执行,这个线程执行完,回来继续执行剩下的bytecode的时候,就不会保证该线程是安全的了,如果说a+=1这多段bytecode会一直执行完,不会被中断,那么就可以保证线程安全了。
  • Python其实只是语言的规范,关键起作用的是语言解释器,我们最常见的有cpython,jpython,GIL是在cpython中的,在jpyhton中是没有GIL的。
  • Python的多线程到底是不是鸡肋,每个语言都有它的优势同时也有它的缺点,比如,nodejs就是单进程单线程的,对于CPU密集型的程序,多线程的意义确实不大,但是对于我们来说,大多数情况下编写的都是IO密集型的程序,IO密集型的程序,查询数据库,请求网络资源,读写文件都属于IO操作,执行一段代码的时候,绝大多数时间都花在io操作上的程序,为io密集型程序,按照时间段消耗来划分。Python的多线程对于IO密集型程序是有一定的意义的,把线程等待的时间,换到别的线程使用CPU,这就是多线程在IO密集型程序中的优势。

你可能感兴趣的:(Python中的多线程深入解析)