Python 多线程和线程池

本文详细介绍了Python的多线程和线程池,包括GIL、线程的创建与同步、线程锁、信号量以及线程池的使用。重点讨论了GIL对计算密集型和I/O密集型任务的影响,以及如何通过线程池来提高IO密集型任务的效率。
摘要由CSDN通过智能技术生成

一,前言

  • 进程:是程序,资源集合,进程控制块组成,是最小的资源单位
    • 特点:就对Python而言,可以实现真正的并行效果
    • 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦  
  • 线程:是进程中最小的执行单位。
    • 特点无法利用多核,无法实现真正意义上是并行效果。
    • 优点:对于IO密集型的操作可以很好利用IO阻塞的时间

二,GIL(全局解释器锁)

  python目前有很多解释器,目前使用最广泛的是CPython,还有PYPY和JPython等解释器,但是使用最广泛的还是CPython解释器,而对于全局解释器锁来说,就是在CPython上面才有的,它的原理是在解释器层面加上一把大锁,保证同一时刻只能有一个python线程在解释器中执行。

  对于计算密集型的python多线程来说,无法利用到多线程带来的效果, 在2.7时计算密集型的python多线程执行效率比顺序执行的效率还低的多,在python3.5中对这种情况进行了优化,基本能实现这种多线程执行时间和顺序执行时间差不多的效果。

  对于I/O密集型的python多线程来说,GIL的影响不是很大,因为I/O密集型的python多线程进程,每个线程在等待I/O的时候,将会释放GIL资源,供别的线程来抢占。所以对于I/O密集型的python多线程进程来说,还是能比顺序执行的效率要高的。

  python的GIL这个东西。。。比较恶心,但是由于CPython解释器中的很多东西都是依赖这个东西开发的,如果改的话,将是一件浩大的工程。。。所以到现在还是存在这个问题,这也是python最为别人所诟病的地方。。。

三,多线程

  多线程相当于一个并发(concunrrency)系统。并发系统一般同时执行多个任务。如果多个任务可以共享资源,特别是同时

写入某个变量的时候,就需要解决同步的问题,比如多线程火车售票系统:两个指令,一个指令检查票是否卖完,另一个指令,多

个窗口同时卖票,可能出现卖出不存在的票。

  3.1 python实现多线程

  python实现多线程有两种方式,分别是直接调用和继承调用,如下实例:

  直接调用:

import threading
import time


# 定义线程运行函数
def mv():
    print('播放=========')
    time.sleep(2)
    print('ending=======')


# 带参数方式
def play(name):
    print("打游戏======"+name)
    time.sleep(3)
    print("ending======")


if __name__ == '__main__':
    th = threading.Thread(target=mv)
    th2 = threading.Thread(target=play, args=("LOL",))
    th.start()
    th2.start()

 

继承调用:

import threading
import time


class MyThread(threading.Thread):
    def __init__(self, num):
        super(MyThread, self).__init__()
        self.num = num

    def run(self):
        print("play game %s======" % self.num)
        time.sleep(2)
        print("end play")


if __name__ == '__main__':
    mt = MyThread(1)
    mt2 = MyThread(2)
    mt.start()
    mt2.start()  

  可以看到直接调用是导入threading模块并定义一个函数,之后实例化threading.Thread类的时候,将刚定义的函数名通过target参数传递进去,然后调用实例的start()方法启动一个线程。

  而继承式调用是创建一个类继承自threading.Thread类,并在构造方法中调用父类的构造方法,之后重写run方法,run方法中就是每个线程起来之后执行的内容,就类似于前面通过target参数传递进去的函数。之后以这个继承的类来创建对象,并执行对象的start()方法启动一个线程。

  从这里可以看出,其实。。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值