Python 多线程编程
Thread类
class Thread: def __init__(self,group=None,target=None,name=None,args=(),kwargs=None,*,daemon=None)
-
group:None,为日后扩展 ThreadGroup 类实现而保留。
-
target:run() 方法调用的目标函数。
-
name:线程名。默认值为Thread-N。
-
args:传递给目标函数的位置参数元组。
-
kwargs:传递给目标函数的关键字参数字典。
-
daemon:守护线程。
Thread类的常用方法和属性
start():启动线程,在一个线程里最多只能被调用一次。
run():调用 target 传递的目标函数,并从 args 和 kwargs 分别获取的位置和关键字参数。
name:线程名。
getName():获取线程名。
setName():设置线程名。
ident:线程标识符,是个非零整数。如果线程尚未启动则为None。
daemon:是否是守护线程的布尔值,默认为False。
isDaemon():返回线程是否是守护线程。
setDaemon():设置线程为守护线程。
join([time]):阻塞调用该方法的线程,直到被调用该方法的线程结束或超时。
is_alive():返回线程是否存活。
threading模块常用方法和属性
active_count():返回当前存活的 Thread 对象的计数。
enumerate():以列表形式返回当前存活的 Thread 对象。
current_thread():返回当前对应调用者的控制线程的 Thread 对象。
main_thread():返回主 Thread 对象。
get_ident():返回当前线程的"线程标识符"。
创建线程
-
可调用对象传递给构造函数
-
重写子类的 run() 方法
1. 可调用对象传递给构造函数
import threading import time def func(n): print("task", n) time.sleep(2) for i in range(2): t = threading.Thread(target=func, args=(i,)) # 创建线程 t.start() # 启动线程
2. 重写子类的 run() 方法
import threading import time class MyThread(threading.Thread): def __init__(self, n): super().__init__() self.n = n def run(self): print("task", self.n) time.sleep(2) for i in range(2): t = MyThread(i) t.start()
全局解释器锁
全局解释器锁(Global Interpreter Lock,简称GIL),是计算机程序设计语言解释器用于同步线程的工具,使得在同一进程内任何时刻仅有一个线程在执行。即使在多核CPU平台上,同一时刻也只有一个获得GIL的线程在执行,其他线程处于阻塞状态。
-
CPython使用操作系统的原生线程,由操作系统负责调度。
-
每个解释器进程有唯一的主线程和用户定义的任意数量子线程。
-
每个解释器进程有且仅有一个GIL,当解释器启动时,主线程获取GIL。
-
线程执行前要先获取GIL,当遇到I/O操作时释放GIL。
线程锁
原始锁处于"锁定"或者"非锁定"状态,被创建时是非锁定状态。它有两个基本方法:acquire(),release()。
-
当状态是非锁定时,线程调用 acquire() 获取锁,并阻塞其他线程,直到锁被释放,将状态修改为锁定。
-
当状态是锁定时,任何线程都可以调用 release() 释放锁,将状态修改为非锁定。
import threading import time lock = threading.Lock() def func(n): lock.acquire() # 获取锁 print("task", n) lock.release() # 释放锁 time.sleep(2) for i in range(2): t = threading.Thread(target=func, args=(i,)) t.start()
信号量
信号量管理一个内部计数器,调用 acquire() 方法时计数器-1,调用 release() 方法时计数器+1。当计数器为0时将会阻塞,直到线程调用 release() 方法。
import threading import time semaphore = threading.BoundedSemaphore(2) def func(n, se): se.acquire() print("task", n) time.sleep(2) se.release() for i in range(2): t = threading.Thread(target=func, args=(i,semaphore)) t.start()
事件
事件是线程之间的一种通信机制:一个线程发出事件信号,其他线程等待该信号。
事件对象管理一个内部标志Flag,初始为false。调用 set() 方法可将其设置为 true,调用 clear() 方法可将其设置为false,调用 wait() 方法将阻塞线程直到标志为 true。
import threading import time event = threading.Event() def func(): print(threading.current_thread().getName(), "ready") time.sleep(3) event.wait() print(threading.currentThread().getName(), "go") for i in range(2): t = threading.Thread(target=func) t.start() print("Ready?Go!") event.set()