Python通用编程规范-06 并发与并行

本文介绍了Python中的并发编程,强调了线程在阻塞IO场景中的应用,但由于GIL的存在,多线程并不适用于并行计算。推荐在需要协调线程工作时使用Queue。此外,文章提倡使用协程来处理并发,协程具有较低的内存开销和灵活的调度。最后,对于并行计算,建议使用多进程库multiprocessing,尤其是当任务间不需要共享状态时。
摘要由CSDN通过智能技术生成

6.1 线程

6.1.1 多线程适用于阻塞式IO场景,不适用于并行计算场景

Python的标准实现是CPython
CPython执行Python代码分为2个步骤:首先,将文本源码解释编译为字节码,然后再用一个解释器去解释运行字节码。字节码解释器是有状态的,需要维护该状态的一致性,因此使用了GILGlobal Interpreter Lock,全局解释器锁)。
GIL的存在,使得CPython在执行多线程代码的时候,同一时刻只有一个线程在运行,无法利用多CPU提高运算效率。但是这个特点也带来了一个好处:CPython运行多线程的时候,内部对象缺省就是线程安全的。这个特性,被非常多的Python库开发者所依赖,直到CPython的开发者想要去除GIL的时候,发现已经有大量的代码库重度依赖
这个GIL带来的内部对象缺省就是线程安全的特性,变成一个无法解决的问题了。
虽然多线程在并行计算场景下无法带来好处,但是在阻塞式IO场景下,却仍然可以起到提高效率的作用。这是因为阻塞式IO场景下,线程在执行IO操作时并不需要占用CPU时间,此时阻塞IO的线程可以被挂起的同时继续执行IO操作,而让出CPU时间给其他线程执行非IO操作。这样一来,多线程并行IO操作就可以起到提高运行效率的作用了。
综上,Python的标准实现CPython,由于GIL的存在,同一个时刻只能运行一个线程,无法充分利用多CPU提升运算效率,因此Python的多线程适用于阻塞式IO的场景,不适用于并行计算的场景。
下面举一个对计算量有要求的求一个数的因数分解的代码实例,来说明Python多线程不适用于并行计算的场景:

# -*- coding:utf-8 -*-
from time import time
from threading import Thread


def factorize(number):
    for i in range(1, number + 1):
        if number % i == 0:
            yield i


class FactorizeThread(Thread):
    def __init__(self, number):
        Thread.__init__(self)
        self.number = number

    def run(self):
        self.factors = list(factorize(self.number))


def test(numbers):
    start = time()
    for number in numbers:
        list(factorize(number))
        end = time()
        print('Took %.3f seconds' % (end - start))


def test_thread(numbers):
    start = time()
    threads = []
    for number in numbers:
        thread = FactorizeThread(number)
        thread.start()
        threads.append(thread)
        for t in threads:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值