Python高级开发之多线程(Multithreaded)初识

简介

在多线程(multithreaded,MT)编程出现之前,计算机程序的执行是由单个步骤序列组 成的,该序列在主机的 CPU 中按照同步顺序执行。要是让这些独立的任务同时运行,会怎么样呢?很明显,这种并行处理方式可以显著地提高整个任务的性能。这就是多线程编程。

多线程特点:异步、多并发和不确定性。

多线程程序在读取 I/O 终端通道时不能阻塞,因为用户输入的到达时间是不确定的,并且阻塞会妨碍 其他 I/O 通道的处理。串行程序必须使用非阻塞 I/O 或拥有计时器的阻塞 I/O(以保证阻塞只是暂时的)。

进程(process)和线程(thread)

进程(process)

又叫重量级进程,是一个执行中的程序,被加载到计算机中调用,拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据,彼此之间采用进程通信(IPC)方式共享信息。

线程(thread)

又叫轻量级进程,与进程类似,在同一个进程下执行的,并 共享相同的上下文,您可以把他看做一些迷你进程。

线程和Python

全局解释器锁(Global Interpreter Locks)

Python 代码的执行是由 Python 解释器进行控制的。Python 在设计时是这样考虑的,在主循环中同时只能有一个控制线程在执行,就像单核 CPU 系统中的多进程一样。内存中可以有许多程序,但是在任意给定时刻只能有一个程序在运行。同理,尽管 Python 解释器中可以运行多个线程,但是在任意给定时刻只有一个线程会被解释器执行。

对 Python 虚拟机的访问是由全局解释器锁(GIL)控制的。这个锁就是用来保证同时只能有一个线程运行的。在多线程环境中,Python 虚拟机将按照下面所述的方式执行。

  1. 设置 GIL。
  2. 切换进一个线程去运行。
  3. 执行下面操作之一:a.指定数量的字节码指令。b.线程主动让出控制权(可以调用 time.sleep(0)来完成)。
  4. 把线程设置回睡眠状态(切换出线程)。
  5. 解锁 GIL。
  6. 重复上述步骤。

当调用外部代码(即,任意 C/C++扩展的内置函数)时,GIL 会保持锁定,直至函数执行结束(因为在这期间没有 Python 字节码计数)。

退出线程

退出方法:

  1. 调用诸如 thread.exit()
  2. 引入sys,调用sys.exit()
  3. 抛出 SystemExit 异常

注意:在主线程退出之后,所有其他线程都会在没有清理的情况下直接退出。

Python中使用线程

当你在 Python 交互环境中尝试输入以下指令以确定您的解释器是否支出线程时可能会出现两种情况:

>>> import thread
>>>

上述线程可用,不会产生错误

>>> import thread
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'thread'

上述表示线程不可用,您可能需要重新编译你的Python解释器才能够使用线程。以下是我个人对 Python3.x 出现这个问题的说明:

  • Python3.x中,为了避免某些不确定问题,thread 被改名为 _thread。
  • 或者您可以使用以下兼容写法:
>>> if sys.version[:1] == "3":import _thread as thread
... else:import thread

不使用线程的情况

from time import sleep, ctime


def func_one():
    print("Started func_one at", ctime())
    sleep(4)
    print('func_one finished at', ctime())


def func_two():
    print("Started func_two at", ctime())
    sleep(4)
    print('func_two finished at', ctime())


def func_three():
    print("Started func_three at", ctime())
    sleep(4)
    print('func_three finished at', ctime())


def main():
    print("Function main start at:", ctime())
    func_one()
    func_two()
    func_three()
    print("Function main finished at:", ctime())


if __name__ == '__main__':
    main()

这是一个普通的单线程式函数,按照时间线来决定走向,sleep()函数表示让程序“睡“几秒,我们预估计程序的执行时间为4 + 4 +4 + 代码开销 = 12+。下面是展示结果:

Function main start at: Mon Aug 13 18:01:18 2018
Started func_one at Mon Aug 13 18:01:18 2018
func_one finished at Mon Aug 13 18:01:22 2018
Started func_two at Mon Aug 13 18:01:22 2018
func_two finished at Mon Aug 13 18:01:26 2018
Started func_three at Mon Aug 13 18:01:26 2018
func_three finished at Mon Aug 13 18:01:30 2018
Function main finished at: Mon Aug 13 18:01:30 2018

Process finished with exit code 0

看出来刚好12秒,原因:今天是2018年08月13日,cpu运算速度较快,完全没有感觉出来。

猜你喜欢

转载自blog.csdn.net/qq_33567641/article/details/81632863
今日推荐