跳转至

什么是线程

线程是进程中的不同执行线。 让我们把一个程序想象成一个蜂巢,在这个蜂巢内部有一个收集花粉的过程。 这个采集过程是由几只工蜂同时工作来完成的,以解决花粉不足的问题。 工蜂扮演着线程的角色,在进程内部活动并共享资源来执行它们的任务。

线程属于同一个进程,共享同一个内存空间。 因此,开发人员的任务是控制和访问这些内存区域。

使用线程的优点和缺点

在决定使用线程时必须考虑一些优点缺点,这取决于用于实现解决方案的语言和操作系统。

使用线程的优势如下所示:

  • 同一进程内的线程通信数据定位共享信息的速度快
  • 线程的创建比进程的创建成本更低,因为不需要复制主进程上下文中包含的所有信息
  • 通过处理器的高速缓存优化内存访问,充分利用数据局部性(data locality)的优势。

使用线程的缺点如下:

  • 数据共享允许快速通信。 但是,它也允许缺乏经验的开发人员引入难以解决的错误。
  • 数据共享限制了解决方案的灵活性。 例如,迁移到分布式架构可能会让人头疼。 通常,它们限制了算法的可扩展性。

在 Python 编程语言中,由于 GIL,使用计算密集型(CPU-bound)的线程可能会损害应用程序的性能。

理解不同类型的线程

有两种类型的线程,内核线程用户线程内核线程是由操作系统创建和管理的线程, 其上下文的交换调度结束都由当前操作系统的内核来进行管理。 对于用户线程,这些状态由(package)开发人员控制。

我们可以引用每种线程的一些优点:

线程类型 优点 缺点
内核线程 一个内核线程其实就是一个进程. 因此即使一个内核线程被阻塞了,其他的内核线程仍然可以运行。
内核线程可以在不同的 CPU 上运行。
创建线程和线程间同步的消耗太大
实现依赖于平台
用户线程 用户线程的创建和线程间同步的开销较少
用户线程是平台无关的。
同一进程中的所有用户线程都对应一个内核线程. 因此,若该内核线程被阻塞,则所有相应的用户线程都会被阻塞。
不同用户线程无法运行在不同CPU上

线程的状态

线程的生命周期有五种可能的状态。它们如下:

  • 新建(Creation): 该过程的主要动作就是创建一个新线程, 创建完新线程后,该线程被发送到待执行的线程队列中。
  • 运行(Execution): 该状态下,线程获取到并消耗CPU资源。
  • 就绪(Ready): 该状态下,线程在待执行的线程队列中排队,等待被执行
  • 阻塞(Blocked): 该状态下,线程由于等待某个事件(例如I/O操作)的出现而被阻塞. 这时线程并不使用CPU。
  • 死亡(Concluded): 该状态下,线程释放执行时使用的资源并结束整个线程的生命周期。

是使用threading模块还是_thread模块

Python提供了两个模块来实现基于系统的线程: _thread模块(该模块提供了使用线程相关的较低层的API; 它的文档可以在http://docs.python.org/3.3/library/_thread.html 找到)和threading模块(该模块提供了使用线程相关的更高级别的API; 它的文档可以在 http://docs.python.org/3.3/library/threading.html 中找到). threading模块提供的接口要比_thread模块的结构更友好一些. 至于具体选择哪个模块取决于开发者, 如果开发人员发现在较低级别使用线程很容易,实现他们自己的线程池并拥抱锁和其他原始功能(features),他/她宁愿使用_thread。 否则,threading是最明智的选择。


最后更新: 2023年3月1日
创建日期: 2023年3月1日