📅  最后修改于: 2023-12-03 15:19:34.563000             🧑  作者: Mango
线程是程序执行的一条路径,一个进程可以有多个线程同时执行不同的任务,利用了多核处理器的优势,提高了程序的执行效率。Python的内置模块 threading
可以方便地创建、操作线程。
使用 threading
模块的 Thread
类创建一个新的线程,示例如下:
import threading
def worker():
"""线程函数"""
print('This is a new thread.')
# 创建线程
t = threading.Thread(target=worker)
# 启动线程
t.start()
该代码会输出一行文字:
This is a new thread.
其中,target
参数指定线程函数,start
方法启动线程。注意,线程并不是马上运行,而是等待 CPU 调度。
多个线程共享同一份数据时,可能会出现数据不一致、竞争条件的问题。Python 的 threading
模块提供了一些同步工具来解决这些问题。
线程之间竞争一份数据时,可以使用锁来保证同一时刻只有一个线程能够访问数据。
import threading
# 共享数据
a = 0
# 创建互斥锁
lock = threading.Lock()
def worker():
"""线程函数"""
global a, lock
for i in range(1000000):
# 获取锁
lock.acquire()
a += 1
# 释放锁
lock.release()
# 创建线程
t1 = threading.Thread(target=worker)
t2 = threading.Thread(target=worker)
# 启动线程
t1.start()
t2.start()
# 等待线程结束
t1.join()
t2.join()
# 输出结果
print(a)
由于两个线程对 a
进行了 100 万次的加一操作,最终输出的结果应该是 2 百万。如果不使用锁,输出结果会小于 2 百万,因为两个线程会竞争访问 a
。
信号量用于限制同时访问共享资源的线程数量。
import threading
# 共享资源
s = threading.Semaphore(2)
def worker():
"""线程函数"""
global s
with s:
print('Thread {} is running.'.format(threading.current_thread().name))
# 创建线程
t1 = threading.Thread(target=worker, name='A')
t2 = threading.Thread(target=worker, name='B')
t3 = threading.Thread(target=worker, name='C')
# 启动线程
t1.start()
t2.start()
t3.start()
使用 threading.Semaphore(2)
创建了一个限制同时访问资源的数量为 2 的信号量。输出结果是:
Thread A is running.
Thread B is running.
Thread C is running.
由于只有两个线程能够获得信号量,因此线程 C 需要等待线程 A 或线程 B 中的一个结束后才能开始运行。
线程池是一组预先创建的线程,可以提高线程的复用性,减少线程的创建和销毁所带来的开销,提高程序性能。
Python 的 concurrent.futures
模块提供了线程池和进程池的实现。下面是一个使用 concurrent.futures.ThreadPoolExecutor
实现线程池的例子:
import concurrent.futures
def worker(index):
"""线程函数"""
return 'Task {} is done.'.format(index)
# 创建线程池
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
# 提交任务
futures = [executor.submit(worker, i) for i in range(10)]
# 获取结果
for future in concurrent.futures.as_completed(futures):
print(future.result())
max_workers=4
指定线程池中最多有 4 个线程同时执行任务。我们提交了 10 个任务,并用 as_completed
方法获取执行结果。
执行结果:
Task 5 is done.
Task 6 is done.
Task 7 is done.
Task 8 is done.
Task 9 is done.
Task 0 is done.
Task 1 is done.
Task 2 is done.
Task 3 is done.
Task 4 is done.
Python 的线程模块 threading
提供了创建、操作线程的接口,多个线程之间共享数据时需要使用同步工具,例如锁、信号量、条件变量等。使用线程池可以提高程序性能,减少线程创建和销毁所带来的开销。