Effective Python 读书笔记: 第37条: 可以用线程来执行阻塞式I/O,但不要用它做平行计算

# -*- encoding: utf-8 -*-

import select
from threading import Thread
from time import time

'''
第37条: 可以用线程来执行阻塞式I/O,但不要用它做平行计算

关键:
1 python实现
CPython运行python过程:
1) 源码->字节码
2)解释器运行字节码
为了保证一致行,采用GIL

2 GIL
含义: 全局解释器锁
本质: 互斥锁
作用: 防止多线程导致字节码解释器的不一致性
缺点: 无法实现多线程,因为同一时刻,只有一条线程可以执行

3 多线程
优点:
1) 多线程使得程序看上去能在同一时间做很多事情
2) 处理阻塞式I/O,借助线程,把程序与耗时的I/O操作分开
例如: 读写文件,网络通信

阻塞式I/O程序样例:
def slowSystemCall():
    select.select([], [], [], 0.1)


def runSystemCall():
    start = time()
    for value in range(10):
        slowSystemCall()
    end = time()
    print "slow system call costs: {value} seconds".format(
        value=end - start
    )
    
分析:
主线程会卡在select调用,如果要同时执行塞式I/O操作和计算操作,需要把
系统调用放到其他线程中。

4 总结
GIL全局解释器锁导致python多线程不能平行执行字节码
但是python多线程仍然有用,可以模拟同一时刻执行多个任务,
平行执行多个系统调用,执行阻塞式I/O操作的同时,执行运算操作

参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''

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


def compute():
    numbers = [2139079, 1214759, 1516637, 1852285]
    start = time()
    for number in numbers:
        list(factorize(number))
    end = time()
    print "cost: {value} seconds".format(
        value=end - start
    )


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

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


def threadCompute():
    numbers = [2139079, 1214759, 1516637, 1852285]
    start = time()
    threads = []
    for number in numbers:
        thread = FactorizeThread(number)
        thread.start()
        threads.append(thread)

    for thread in threads:
        thread.join()
    end = time()
    print "multiple threads cost: {value} seconds".format(
        value=end - start
    )

def slowSystemCall():
    select.select([], [], [], 0.1)


def runSystemCall():
    start = time()
    for value in range(10):
        slowSystemCall()
    end = time()
    print "slow system call costs: {value} seconds".format(
        value=end - start
    )



def optimizedRunSystemCall():
    start = time()
    threads = []
    for value in range(10):
        thread = Thread(target=slowSystemCall())
        thread.start()
        threads.append(thread)
    for thread in threads:
        thread.join()
    end = time()
    print "optimized system call costs: {value} seconds".format(
        value=end - start
    )


def computeLocation(index):
    pass


def runComputeLocation():
    start = time()
    threads = []
    for value in range(10):
        thread = Thread(target=computeLocation(value))
        thread.start()
        threads.append(thread)
    for thread in threads:
        thread.join()
    end = time()
    print "computeLocation costs: {value} seconds".format(
        value=end - start
    )


def process():
    compute()
    threadCompute()
    runSystemCall()
    optimizedRunSystemCall()
    runComputeLocation()


if __name__ == "__main__":
    process() 

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/88958018