多线程编程对于具有如下特点的编程任务而言是非常理想的:本质上是异步的;需要多个并发活动;每个活动的处理顺序可能是不确定的,或者说是随机的、不可预测的。

这种编程任务可以被组织或划分成多个执行流,其中每个执行流都有一个指定要完成的任务。

  • UserRequestThread

负责读取客户端输入,该输入可能来自 I/O 通道;程序将创建多个线程,每个客户端一个,客户端的请求将会被放入队列中

  • RequestProcessor

该线程负责从队列中获取请求并进行处理,为第 3 个线程提供输出

  • ReplyThread

负责向用户输出,将结果传回给用户(如果是网络应用),或者把数据写到本地文件系统或数据库中

进/线程

进程

计算机程序只是存储在磁盘上的可执行二进制(或其他类型)文件,只有把它们加载到内存中并被操作系统调用,才拥有其生命期

进程(有时称为重量级进程)则是一个执行中的程序,每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据

操作系统管理其上所有进程的执行,并为这些进程合理地分配时间;进程也可以通过派生(fork或spawn)新的进程来执行其他任务,不过因为每个新进程也都拥有自己的内存和数据栈等,所以只能采用进程间通信(IPC)的方式共享信息

线程

线程(有时候称为轻量级进程)与进程类似,不过它们是在同一个进程下执行的,并共享相同的上下文;可以将它们认为是在一个主进程或“主线程”中并行运行的一些“迷你进程”

线程包括开始、执行顺序和结束三部分;它有一个指令指针,用于记录当前运行的上下文;当其他线程运行时,它可以被抢占(中断)和临时挂起(也称为睡眠),这种做法叫做让步(yielding)

一个进程中的各个线程与主线程共享同一片数据空间,因此相比于独立的进程而言,线程间的信息技术和通信更加容易;线程一般是以并发方式执行的,正是由于这种并行和数据共享机制,使得多任务间的协作成为可能

Python 线程

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

全局解释器锁

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

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

    使用线程

    Python 提供了多个模块来支持多线程编程,包括 thread、threading 和 Queue 模块等
  • 程序是可以使用 thread 和 threading 模块来创建与管理线程:thread 模块提供了基本的线程和锁定支持;而 threading 模块提供了更高级别、功能更全面的线程管理
  • 使用 Queue 模块,用户可以创建一个队列数据结构,用于在多线程之间进行共享

PS.避免使用 thread 模块

  • threading 模块更加先进,有更好的线程支持,并且 thread 模块中的一些属性会和 threading 模块有冲突
  • 低级别的 thread 模块拥有的同步原语很少(只有一个),而 threading 模块则有很多
  • thread 模块对于进程何时退出没有控制,当主线程结束时,所有其他线程也都强制结束,不会发出警告或者进行适当的清理,而 threading 模块能通过守护线程确保重要的子线程在进程退出前结束

    thread 模块

    threading 模块

    thread 类

    多线程实践

    同步原语

    锁示例

    信号量示例

    生产/消费者

    Queue 模块

    3.x 重命名为:queue

    线程的替代

    subprocess 模块

    是派生进程的主要替代方案,可以单纯地执行任务,或者通过标准文件(stdin、stdout、stderr)进行进程间通信

    multiprocessing 模块

    2.6 版本起引入,允许为多核或多CPU 派生进程,其接口与 threading模块非常相似。该模块同样也包括在共享任务的进程间传输数据的多种方式

    concurrent.futures 模块

    这是一个新的高级库,它只在“任务”级别进行操作,也就是说,不再需要过分关注同步和线程/进程的管理了;只需要指定一个给定了“worker”数量的线程/进程池,提交任务,然后整理结果。该模块自 Python 3.2 版本起引入,不过有一个 Python 2.6+ 可使用的移植版本,其网址为:http://code.google.com/p/pythonfutures