type
status
date
slug
summary
tags
category
icon
password

线程和进程

线程和进程定义

在实现了线程的操作系统中,线程是操作系统能够进行运算调度的最小单位。它被包含在进程中,是进程中的实际运作单位。一个程序的执行实例就是一个进程。
  • 进程(Process):计算机中的程序关于某数据集合上的一次运行行动,是系统进行资源分配和调度的基本单位(管理资源用的), 是操作系统解构的基础。
 
  • 进程和程序的关系:程序是源代码编译后的文件,而这些文件存放在磁盘上当程序被操作系统加载到内存中,就是进程,进程中存放指令和数据(资源), 它也是线程的容器。
  • Linux进程有父进程和子进程,Windows的进程是平等关系。
  • 线程:有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元,一个标注的线程有线程ID,当前指令指针(PC)、寄存器集合和堆、栈组成。在许多系统中,创建一个线程比创建一个进程快10-100倍。

线程和进程的资源问题

现代操作系统提出进程的概念, 每一个进程都认为自己独占所有的计算机硬件资源。
进程就是独立的王国,进程间不可以随便的共享数据。(可以进程间通讯,代价比较高)
线程就是省份,同一个进程内的线程可以共享进程的资源,每一个线程拥有自己独立的堆栈

线程的状态

状态
含义
就绪(Ready)
线程能够运行,但在等待被调度。可能线程刚刚
运行(Running)
线程正在运行
阻塞(Blocked)
线程等待外部事件发生而无法运行,如I/O操作
终止(Terminated)
线程完成,或退出,或被取消
notion image

python中的进程和线程

运行程序会启动一个解释器进程,线程共享一个解释器进程。
 

Python线程开发

Python的线程开发使用标准库threading.
进程靠线程执行代码, 至少有一个主线程, 其它线程是工作线程.
主线程是第一个启动的线程.
  • 父线程: 如果线程A中启动了一个线程B, A就是B的父线程
  • 子线程: B就是A的子线程

Thread类

参数名
含义
target
线程调用的对象, 就是目标函数
name
为线程起个名字
args
为目标函数传递实参, 元组
kwargs
为目标函数传递关键字参数, 字典
deamon

线程启动

通过threading.Thread创建一个线程对象, target是目标函数, 可以使用name为线程指定线程名称.
但是线程没有启动, 需要调用start方法.
线程之所以执行函数, 是因为线程中就是要执行代码的, 而最简单的代码封装就是函数, 所以还是函数调用.
函数执行完, 线程也就退出了.
那么, 如果不让线程退出, 或者让线程一直工作怎么办呢?

线程退出

Python没有提供线程退出的方法, 线程在下面情况时退出:
  • 线程函数内语句执行完毕
  • 线程函数中抛出未处理的异常
注: 工作线程即使异常退出, 主线程依然可以运行.
Python的线程没有优先级, 没有线程组的概念, 也不能被销毁, 停止, 挂起, 那也就没有恢复, 中断了.

线程的传参

线程传参和函数传参没什么区别, 本质上就是函数传参.

threading模块的属性和方法

名称
含义
current_thread()
返回当前线程对象
main_thread()
返回主线程对象
active_count()
当前处于alive转态的线程数
enumerate()
返回所有活着的线程的列表, 不包括已经终止的线程和未开始的线程
get_ident()
返回当前线程的ID, 非0整数
active_count(), enumerate()方法返回的值还包括主线程.

Thread实例的属性和方法

名称
含义
name
只是一个名字, 只是个标识符, 名称可以重名. getName(), setName()获取, 设置这个名词
ident
线程ID, 它是非0整数. 线程启动后才会有ID, 否则为None. 线程退出, 此ID依旧可以访问. 此ID可以重复使用.
is_alive()
返回线程是否活着, 是为True, 否为False
注意:线程名name可以重复, 但是线程ID是不能重复的, 但可以在线程退出后再利用.
从上面的例子还可以看出, 一个线程只能被运行一次, 如果线程结束了, 那么再次将这个线程对象重启是会报错.
名称
start()
启动线程. 每个线程必须且只能执行该方法一次
run()
运行线程函数
为了掩饰, 派生一个Thread的子类