第4课-并发编程基础
第4课:并发编程基础
课程目标
通过本课程学习,你将能够:
- 理解进程与线程的区别和联系
- 深入理解Python的GIL(全局解释器锁)机制
- 熟练使用threading模块进行多线程编程
- 掌握线程同步和锁的使用
- 理解asyncio异步编程模型
- 掌握协程的概念和使用
- 为后续学习OneForAll的高性能并发处理打下基础
4.1 进程与线程
4.1.1 什么是进程?
进程(Process)的定义:
进程是程序在计算机上的一次执行活动,是系统进行资源分配和调度的基本单位。
进程的特点:
- 独立性:每个进程都有独立的内存空间
- 资源拥有:每个进程拥有独立的资源(文件、内存等)
- 并发性:多个进程可以并发执行
- 动态性:进程是动态产生和消亡的
进程的状态:
"""
进程的三种基本状态:
1. 就绪态(Ready):进程已获得除CPU外的所有资源,等待CPU调度
2. 运行态(Running):进程正在CPU上执行
3. 阻塞态(Blocked):进程因等待某个事件而暂停执行
状态转换:
就绪态 → 运行态:进程被CPU调度
运行态 → 就绪态:时间片用完或被高优先级进程抢占
运行态 → 阻塞态:等待I/O或其他事件
阻塞态 → 就绪态:等待的事件发生
"""
4.1.2 什么是线程?
线程(Thread)的定义:
线程是进程中的一个执行单元,是CPU调度的基本单位,也被称为轻量级进程。
线程的特点:
- 轻量级:线程的创建和销毁开销小
- 共享资源:同一进程的线程共享内存和资源
- 独立执行:每个线程有独立的执行流
- 通信方便:线程间通信比进程间通信更简单
线程与进程的关系:
"""
进程 vs 线程:
1. 包含关系
进程包含线程,一个进程至少有一个线程(主线程)
进程可以创建多个线程
2. 资源共享
进程:拥有独立的内存空间和资源
线程:共享所属进程的内存和资源
3. 开销对比
进程:创建和销毁开销大,上下文切换开销大
线程:创建和销毁开销小,上下文切换开销小
4. 通信方式
进程:需要使用IPC(进程间通信)机制
线程:可以直接访问共享变量,通信更方便
5. 安全性
进程:相互隔离,一个进程崩溃不影响其他进程
线程:一个线程崩溃可能导致整个进程崩溃
"""
4.1.3 多进程 vs 多线程
多进程的特点:
"""
多进程的优点:
1. 真正的并行执行(多核CPU)
2. 进程间隔离,安全性高
3. 可以充分利用多核CPU
4. 一个进程崩溃不影响其他进程
多进程的缺点:
1. 创建和销毁开销大
2. 进程间通信复杂
3. 内存占用较大
4. 上下文切换开销大
适用场景:
- CPU密集型任务
- 需要真正并行的场景
- 需要高隔离性的场景
"""
多线程的特点:
"""
多线程的优点:
1. 创建和销毁开销小
2. 线程间通信方便
3. 内存占用小
4. 上下文切换开销小
多线程的缺点:
1. 受GIL限制,无法利用多核CPU
2. 需要处理线程安全问题
3. 一个线程崩溃可能影响整个进程
4. 调试相对复杂
适用场景:
- I/O密集型任务
- 需要共享数据的场景
- 需要快速响应的场景
"""
4.1.4 Python中的多进程
使用multiprocessing模块:
import multiprocessing
import time
import os
def worker(name, delay):
"""工作线程函数"""
print(f"Worker {name} started (PID: {os.getpid()})")
time.sleep(delay)
print(f"Worker {name} finished (PID: {os.getpid()})")
def multiprocessing_example():
"""多进程示例"""
print(f"Main process PID: {os.getpid()}")
# 创建进程
process1 = multiprocessing.Process(target=worker, args=("A", 2))
process2 = multiprocessing.Process(target=worker, args=("B", 3))
# 启动进程
process1.start()
process2.start()
# 等待进程结束
process1.join()
process2.join()
print("All processes finished")
# 使用示例
if __name__ == "__main__":
multiprocessing_example()
进程间通信:
import multiprocessing
def producer(queue):
"""生产者进程"""
for i in range(5):
queue.put(f"Item {i}")
print("Producer finished")
def consumer(queue):
"""消费者进程"""
while True:
item = queue.get()
if item == "DONE":
break
print(f"Consumed: {item}")
print("Consumer finished")
def ipc_example():
"""进程间通信示例"""
# 创建队列
queue = multiprocessing.Queue()
# 创建进程
producer_process = multiprocessing.Process(target=producer, args=(queue,))
consumer_process = multiprocessing.Process(target=consumer, args=(queue,))
# 启动进程
consumer_process.start()
producer_process.start()
# 等待生产者完成
producer_process.join()
# 发送结束信号
queue.put("DONE")
# 等待消费者完成
consumer_process.join()
print("IPC example finished")
# 使用示例
if __name__ == "__main__":
ipc_example()
4.1.5 Python中的多线程
使用threading模块:
import threading
import time
import os
def worker(name, delay):
"""工作线程函数"""
print(f"Worker {name} started (Thread ID: {threading.current_thread().ident})")
print(f"Worker {name} in process {os.getpid()}")
time.sleep(delay)
print(f"Worker {name} finished (Thread ID: {threading.current_thread().ident})")
def threading_example():
"""多线程示例"""
print(f"Main thread ID: {threading.current_thread().ident}")
print(f"Main process PID: {os.getpid()}")
# 创建线程
thread1 = threading.Thread(target=worker, args=("A", 2))
thread2 = threading.Thread(target=worker, args=("B", 3))
# 启动线程
thread1.start()
thread2.start()
# 等待线程结束
thread1.join()
thread2.join()
print("All threads finished")
# 使用示例
if __name__ == "__main__":
threading_example()
线程间共享数据:
import threading
import time
class SharedCounter:
"""共享计数器"""
def __init__(self):
self.value = 0
def increment(self):
"""增加计数"""
self.value += 1
def get_value(self):
"""获取当前值"""
return self.value
def worker(counter, name):
"""工作线程"""
for _ in range(100000):
counter.increment()
print(f"Worker {name} finished")
def shared_data_example():
"""线程间共享数据示例"""
counter = SharedCounter()
# 创建多个线程
threads = []
for i in range(5):
thread = threading.Thread(target=worker, args=(counter, i))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print(f"Final counter value: {counter.get_value()}")
# 注意:由于竞争条件,结果可能不是预期的500000
# 使用示例
if __name__ == "__main__":
shared_data_example()
4.2 GIL(全局解释器锁)机制
4.2.1 什么是GIL?
GIL的定义:
GIL(Global Interpreter Lock,全局解释器锁)是Python解释器中的一种互斥锁,它确保在任何时候只有一个线程在执行Python字节码。
GIL的作用:
"""
GIL的目的:
1. 保护Python对象的内部状态
2. 简化内存管理
3. 防止多线程同时访问Python对象导致的问题
GIL的影响:
1. 多线程无法在多核CPU上真正并行执行Python字节码
2. 同一时刻只有一个线程在执行Python代码
3. I/O密集型任务可以受益于多线程(I/O时会释放GIL)
4. CPU密集型任务无法从多线程中获得性能提升
"""
4.2.2 GIL的工作原理
GIL的获取和释放:
"""
GIL的获取和释放时机:
获取GIL:
1. 线程开始执行Python代码
2. 从I/O操作返回
3. 从等待中唤醒
释放GIL:
1. 执行I/O操作(如文件读写、网络请求)
2. 执行时间片用完(默认约15ms)
3. 执行需要长时间的操作(如某些C扩展函数)
4. 显式释放(在C扩展中)
注意:
- GIL的释放和获取是自动的
- Python代码无法直接控制GIL
- 某些C扩展可以释放GIL以允许并行执行
"""
4.2.3 GIL对多线程的影响
演示GIL的影响:
import threading
import time
def cpu_bound_task(n):
"""CPU密集型任务"""
total = 0
for i in range(n):
total += i * i
return total
def io_bound_task():
"""I/O密集型任务"""
time.sleep(1)
return "Done"
def test_cpu_bound():
"""测试CPU密集型任务"""
print("=== CPU Bound Task ===")
# 单线程
start = time.time()
cpu_bound_task(10000000)
end = time.time()
print(f"Single thread: {end - start:.2f}s")
# 多线程(由于GIL,不会更快)
start = time.time()
threads = []
for _ in range(2):
thread = threading.Thread(target=cpu_bound_task, args=(5000000,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
end = time.time()
print(f"Two threads: {end - start:.2f}s")
def test_io_bound():
"""测试I/O密集型任务"""
print("\n=== I/O Bound Task ===")
# 单线程
start = time.time()
for _ in range(5):
io_bound_task()
end = time.time()
print(f"Single thread: {end - start:.2f}s")
# 多线程(由于I/O时释放GIL,会更快)
start = time.time()
threads = []
for _ in range(5):
thread = threading.Thread(target=io_bound_task)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
end = time.time()
print(f"Five threads: {end - start:.2f}s")
# 使用示例
if __name__ == "__main__":
test_cpu_bound()
test_io_bound()
4.2.4 如何绕过GIL限制
方法1:使用多进程
import multiprocessing
import time
def cpu_intensive_task(n):
"""CPU密集型任务"""
total = 0
for i in range(n):
total += i * i
return total
def use_multiprocessing():
"""使用多进程绕过GIL"""
print("=== Using Multiprocessing ===")
# 单进程
start = time.time()
cpu_intensive_task(10000000)
end = time.time()
print(f"Single process: {end - start:.2f}s")
# 多进程(每个进程有自己的GIL,可以真正并行)
start = time.time()
processes = []
for _ in range(2):
process = multiprocessing.Process(
target=cpu_intensive_task,
args=(5000000,)
)
processes.append(process)
process.start()
for process in processes:
process.join()
end = time.time()
print(f"Two processes: {end - start:.2f}s")
# 使用示例
if __name__ == "__main__":
use_multiprocessing()
方法2:使用C扩展
"""
某些C扩展可以释放GIL,允许并行执行
示例:
- NumPy的数组操作
- Pillow的图像处理
- requests的网络请求(底层使用libcurl)
这些库在执行耗时操作时会释放GIL
"""
import numpy as np
import threading
import time
def numpy_operation():
"""NumPy操作(会释放GIL)"""
# 创建大数组
arr = np.random.rand(10000000)
# 执行计算(C代码,会释放GIL)
result = np.sum(arr * arr)
return result
def test_numpy():
"""测试NumPy的多线程性能"""
print("=== NumPy Multi-threading ===")
# 单线程
start = time.time()
numpy_operation()
end = time.time()
print(f"Single thread: {end - start:.2f}s")
# 多线程(NumPy会释放GIL,可以获得性能提升)
start = time.time()
threads = []
for _ in range(4):
thread = threading.Thread(target=numpy_operation)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
end = time.time()
print(f"Four threads: {end - start:.2f}s")
# 使用示例
if __name__ == "__main__":
test_numpy()
方法3:使用asyncio(异步编程)
import asyncio
import time
async def async_task(name, delay):
"""异步任务"""
print(f"Task {name} started")
await asyncio.sleep(delay) # 模拟I/O操作
print(f"Task {name} finished")
return f"Result {name}"
async def async_main():
"""异步主函数"""
print("=== Asyncio ===")
start = time.time()
# 并发执行多个异步任务
results = await asyncio.gather(
async_task("A", 1),
async_task("B", 2),
async_task("C", 1)
)
end = time.time()
print(f"Total time: {end - start:.2f}s")
print(f"Results: {results}")
# 使用示例
if __name__ == "__main__":
asyncio.run(async_main())
4.3 threading模块使用
4.3.1 创建和启动线程
方法1:使用函数创建线程
import threading
import time
def simple_worker(name):
"""简单的工作线程"""
print(f"Worker {name} started")
time.sleep(2)
print(f"Worker {name} finished")
def create_thread_with_function():
"""使用函数创建线程"""
# 创建线程
thread = threading.Thread(target=simple_worker, args=("A",))
# 启动线程
thread.start()
# 等待线程结束
thread.join()
print("Main thread finished")
# 使用示例
if __name__ == "__main__":
create_thread_with_function()
方法2:使用类创建线程
import threading
import time
class WorkerThread(threading.Thread):
"""工作线程类"""
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
"""线程执行的方法"""
print(f"Worker {self.name} started")
time.sleep(2)
print(f"Worker {self.name} finished")
def create_thread_with_class():
"""使用类创建线程"""
# 创建线程
thread = WorkerThread("A")
# 启动线程
thread.start() #不使用run(),因为不会创建新线程,只是在当前线程执行
# 等待线程结束
thread.join()
print("Main thread finished")
# 使用示例
if __name__ == "__main__":
create_thread_with_class()
方法3:使用线程池
from concurrent.futures import ThreadPoolExecutor
import time
def worker(name, delay):
"""工作线程"""
print(f"Worker {name} started")
time.sleep(delay)
print(f"Worker {name} finished")
return f"Result {name}"
def use_thread_pool():
"""使用线程池"""
print("=== Thread Pool ===")
# 创建线程池
with ThreadPoolExecutor(max_workers=3) as executor:
# 提交任务
future1 = executor.submit(worker, "A", 1)
future2 = executor.submit(worker, "B", 2)
future3 = executor.submit(worker, "C", 1)
# 获取结果
result1 = future1.result()
result2 = future2.result()
result3 = future3.result()
print(f"Results: {result1}, {result2}, {result3}")
# 使用map批量提交任务
with ThreadPoolExecutor(max_workers=3) as executor:
results = executor.map(worker, ["D", "E", "F"], [1, 2, 1])
for result in results:
print(f"Map result: {result}")
# 使用示例
if __name__ == "__main__":
use_thread_pool()
4.3.2 线程属性和方法
线程属性:
import threading
import time
'''
.name() #线程名
.ident() #线程ID
.is_alive() #线程是否活跃
.isDaemon() #检查线程是否为守护线程
.active_count() #当前活动线程数
.enumerate() #获取当前所有活跃线程的列表
'''
def show_thread_info():
"""显示线程信息"""
print(f"Current thread: {threading.current_thread().name}")
print(f"Thread ID: {threading.current_thread().ident}")
print(f"Is alive: {threading.current_thread().is_alive()}")
print(f"Is daemon: {threading.current_thread().isDaemon()}")
def worker(name):
"""工作线程"""
show_thread_info()
time.sleep(2)
print(f"Worker {name} finished")
def thread_properties():
"""线程属性示例"""
print("=== Main Thread ===")
show_thread_info()
# 创建线程并设置属性
thread = threading.Thread(
target=worker,
args=("A",),
name="MyThread",
daemon=False
)
print(f"\n=== Thread Before Start ===")
print(f"Name: {thread.name}")
print(f"Alive: {thread.is_alive()}")
# 启动线程
thread.start()
print(f"\n=== Thread After Start ===")
print(f"Alive: {thread.is_alive()}")
# 等待线程结束
thread.join()
print(f"\n=== Thread After Join ===")
print(f"Alive: {thread.is_alive()}")
# 活跃线程数量
print(f"\nActive threads: {threading.active_count()}")
print(f"Thread list: {threading.enumerate()}")
# 使用示例
if __name__ == "__main__":
thread_properties()
守护线程:
import threading
import time
def daemon_worker():
"""守护线程"""
print("Daemon thread started")
time.sleep(3)
print("Daemon thread finished")
def normal_worker():
"""普通线程"""
print("Normal thread started")
time.sleep(2)
print("Normal thread finished")
def daemon_example():
"""守护线程示例"""
# 创建守护线程
daemon_thread = threading.Thread(target=daemon_worker, daemon=True)
# 创建普通线程
normal_thread = threading.Thread(target=normal_worker, daemon=False)
# 启动线程
daemon_thread.start()
normal_thread.start()
# 只等待普通线程
normal_thread.join()
print("Main thread finished (daemon thread will be terminated)")
# 使用示例
if __name__ == "__main__":
daemon_example()
4.3.3 线程间通信
使用队列(Queue)进行通信:
import threading
import queue
import time
def producer(q, items):
"""生产者线程"""
print("Producer started")
for item in items:
q.put(item)
print(f"Produced: {item}")
time.sleep(0.5)
print("Producer finished")
def consumer(q):
"""消费者线程"""
print("Consumer started")
while True:
try:
item = q.get(timeout=2)
print(f"Consumed: {item}")
q.task_done()
except queue.Empty:
break
print("Consumer finished")
def queue_communication():
"""使用队列进行线程间通信"""
# 创建队列
q = queue.Queue()
# 创建线程
items = ["A", "B", "C", "D", "E"]
producer_thread = threading.Thread(target=producer, args=(q, items))
consumer_thread = threading.Thread(target=consumer, args=(q,))
# 启动线程
consumer_thread.start()
producer_thread.start()
# 等待线程结束
producer_thread.join()
consumer_thread.join()
print("Queue communication finished")
# 使用示例
if __name__ == "__main__":
queue_communication()
使用Event进行通信:
import threading
import time
def worker(event, name):
"""工作线程"""
print(f"Worker {name} waiting for event")
event.wait() # 等待事件被设置
print(f"Worker {name} received event")
time.sleep(1)
print(f"Worker {name} finished")
def event_communication():
"""使用Event进行线程间通信"""
# 创建事件
event = threading.Event()
# 创建线程
threads = []
for i in range(3):
thread = threading.Thread(target=worker, args=(event, i))
threads.append(thread)
thread.start()
time.sleep(2)
print("Setting event")
event.set() # 设置事件,唤醒所有等待的线程
# 等待所有线程结束
for thread in threads:
thread.join()
print("Event communication finished")
# 使用示例
if __name__ == "__main__":
event_communication()
使用Condition进行通信:
import threading
import time
import random
class ProducerConsumer:
"""生产者消费者模型"""
def __init__(self):
self.items = []
self.condition = threading.Condition()
def produce(self, item):
"""生产物品"""
with self.condition:
self.items.append(item)
print(f"Produced: {item}")
self.condition.notify() # 通知消费者
def consume(self):
"""消费物品"""
with self.condition:
while not self.items:
print("Consumer waiting...")
self.condition.wait() # 等待生产者通知
item = self.items.pop(0)
print(f"Consumed: {item}")
return item
def producer(pc):
"""生产者线程"""
for i in range(5):
item = f"Item-{i}"
pc.produce(item)
time.sleep(random.random())
def consumer(pc):
"""消费者线程"""
for _ in range(5):
pc.consume()
time.sleep(random.random())
def condition_communication():
"""使用Condition进行线程间通信"""
pc = ProducerConsumer()
# 创建线程
producer_thread = threading.Thread(target=producer, args=(pc,))
consumer_thread = threading.Thread(target=consumer, args=(pc,))
# 启动线程
consumer_thread.start()
producer_thread.start()
# 等待线程结束
producer_thread.join()
consumer_thread.join()
print("Condition communication finished")
# 使用示例
if __name__ == "__main__":
condition_communication()
4.4 线程同步与锁
4.1.1 为什么需要线程同步?
线程安全问题:
import threading
class Counter:
"""计数器类(不安全)"""
def __init__(self):
self.value = 0
def increment(self):
"""增加计数(不安全)"""
# 这不是原子操作,可能导致竞争条件
temp = self.value
temp += 1
self.value = temp
def get_value(self):
"""获取当前值"""
return self.value
def unsafe_increment(counter):
"""不安全的增加计数"""
for _ in range(100000):
counter.increment()
def race_condition_demo():
"""演示竞争条件"""
counter = Counter()
# 创建多个线程
threads = []
for _ in range(5):
thread = threading.Thread(target=unsafe_increment, args=(counter,))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print(f"Expected: 500000")
print(f"Actual: {counter.get_value()}")
# 由于竞争条件,实际值通常小于预期值
# 使用示例
if __name__ == "__main__":
race_condition_demo()
4.4.2 使用Lock(锁)
基本锁的使用:
import threading
class SafeCounter:
"""线程安全的计数器"""
def __init__(self):
self.value = 0
self.lock = threading.Lock() # 创建锁
def increment(self):
"""线程安全的增加计数"""
with self.lock: # 使用上下文管理器自动获取和释放锁
temp = self.value
temp += 1
self.value = temp
def get_value(self):
"""获取当前值"""
with self.lock:
return self.value
def safe_increment(counter):
"""线程安全的增加计数"""
for _ in range(100000):
counter.increment()
def lock_demo():
"""使用Lock解决竞争条件"""
counter = SafeCounter()
# 创建多个线程
threads = []
for _ in range(5):
thread = threading.Thread(target=safe_increment, args=(counter,))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print(f"Expected: 500000")
print(f"Actual: {counter.get_value()}")
# 使用锁后,结果应该是正确的
# 使用示例
if __name__ == "__main__":
lock_demo()
Lock的手动使用:
import threading
import time
def manual_lock_demo():
"""手动使用Lock"""
lock = threading.Lock()
def worker(name):
print(f"Worker {name} trying to acquire lock")
lock.acquire() # 获取锁
try:
print(f"Worker {name} acquired lock")
time.sleep(1)
print(f"Worker {name} releasing lock")
finally:
lock.release() # 释放锁
# 创建线程
threads = []
for i in range(3):
thread = threading.Thread(target=worker, args=(i,))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print("Manual lock demo finished")
# 使用示例
if __name__ == "__main__":
manual_lock_demo()
Lock的超时获取:
import threading
import time
def lock_timeout_demo():
"""Lock超时获取示例"""
lock = threading.Lock()
def worker(name, timeout):
print(f"Worker {name} trying to acquire lock")
try:
acquired = lock.acquire(timeout=timeout) # 尝试获取锁,带超时
if acquired:
print(f"Worker {name} acquired lock")
time.sleep(2)
print(f"Worker {name} releasing lock")
lock.release()
else:
print(f"Worker {name} failed to acquire lock (timeout)")
except Exception as e:
print(f"Worker {name} error: {e}")
# 创建线程
thread1 = threading.Thread(target=worker, args=("A", -1)) # 无限等待
thread2 = threading.Thread(target=worker, args=("B", 1)) # 1秒超时
thread3 = threading.Thread(target=worker, args=("C", 1)) # 1秒超时
thread1.start()
time.sleep(0.5) # 确保thread1先获取锁
thread2.start()
thread3.start()
# 等待所有线程完成
thread1.join()
thread2.join()
thread3.join()
print("Lock timeout demo finished")
# 使用示例
if __name__ == "__main__":
lock_timeout_demo()
4.4.3 使用RLock(可重入锁)
什么是RLock?
"""
RLock(Reentrant Lock,可重入锁):
- 同一个线程可以多次获取同一个锁
- 避免死锁
- 需要同样次数的释放
适用场景:
- 递归函数
- 同一个线程需要多次获取锁的情况
"""
RLock的使用:
import threading
class RecursiveCounter:
"""使用RLock的递归计数器"""
def __init__(self):
self.value = 0
self.lock = threading.RLock() # 使用RLock
def increment(self):
"""增加计数"""
with self.lock:
self.value += 1
# 可以递归调用,因为RLock是可重入的
if self.value < 100:
self.increment()
def get_value(self):
"""获取当前值"""
with self.lock:
return self.value
def rlock_demo():
"""RLock示例"""
counter = RecursiveCounter()
# 重置计数器
counter.value = 0
# 递归增加
counter.increment()
print(f"Final value: {counter.get_value()}")
print("RLock demo finished")
# 使用示例
if __name__ == "__main__":
rlock_demo()
RLock vs Lock对比:
import threading
def lock_reentrancy_demo():
"""Lock的可重入性对比"""
# Lock不可重入
def use_lock():
lock = threading.Lock()
def inner_function():
with lock: # 这会死锁,因为同一个线程不能重复获取Lock
print("Inner function acquired lock")
with lock:
print("Outer function acquired lock")
try:
inner_function()
except Exception as e:
print(f"Error with Lock: {e}")
# RLock可重入
def use_rlock():
rlock = threading.RLock()
def inner_function():
with rlock: # 这可以工作,因为RLock是可重入的
print("Inner function acquired lock")
with rlock:
print("Outer function acquired lock")
inner_function()
print("Outer function releasing lock")
print("=== Lock (Not Reentrant) ===")
use_lock()
print("\n=== RLock (Reentrant) ===")
use_rlock()
print("Reentrancy demo finished")
# 使用示例
if __name__ == "__main__":
lock_reentrancy_demo()
4.4.4 使用Semaphore(信号量)
什么是Semaphore?
"""
Semaphore(信号量):
- 控制同时访问资源的线程数量
- 内部维护一个计数器
- acquire():计数器减1,如果为0则等待
- release():计数器加1,唤醒等待的线程
适用场景:
- 限制并发连接数
- 控制资源访问数量
- 实现生产者消费者模型
"""
Semaphore的使用:
import threading
import time
def worker(semaphore, name):
"""工作线程"""
print(f"Worker {name} trying to acquire semaphore")
with semaphore:
print(f"Worker {name} acquired semaphore")
time.sleep(2)
print(f"Worker {name} releasing semaphore")
print(f"Worker {name} finished")
def semaphore_demo():
"""Semaphore示例"""
# 创建信号量,最多允许2个线程同时访问
semaphore = threading.Semaphore(2)
# 创建多个线程
threads = []
for i in range(5):
thread = threading.Thread(target=worker, args=(semaphore, i))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print("Semaphore demo finished")
# 使用示例
if __name__ == "__main__":
semaphore_demo()
限制并发连接数:
import threading
import time
import random
class ConnectionPool:
"""连接池(使用Semaphore限制连接数)"""
def __init__(self, max_connections):
self.max_connections = max_connections
self.semaphore = threading.Semaphore(max_connections)
self.active_connections = 0
def acquire_connection(self, name):
"""获取连接"""
print(f"{name} waiting for connection...")
self.semaphore.acquire()
self.active_connections += 1
print(f"{name} acquired connection (active: {self.active_connections})")
def release_connection(self, name):
"""释放连接"""
self.active_connections -= 1
print(f"{name} released connection (active: {self.active_connections})")
self.semaphore.release()
def use_connection(self, name, duration):
"""使用连接"""
self.acquire_connection(name)
try:
time.sleep(duration)
print(f"{name} finished using connection")
finally:
self.release_connection(name)
def connection_pool_demo():
"""连接池示例"""
pool = ConnectionPool(max_connections=3)
# 创建多个线程
threads = []
for i in range(10):
duration = random.uniform(1, 3)
thread = threading.Thread(
target=pool.use_connection,
args=(f"Worker-{i}", duration)
)
threads.append(thread)
thread.start()
time.sleep(0.5) # 错开线程启动时间
# 等待所有线程完成
for thread in threads:
thread.join()
print("Connection pool demo finished")
# 使用示例
if __name__ == "__main__":
connection_pool_demo()
4.4.5 使用BoundedSemaphore(有界信号量)
什么是BoundedSemaphore?
"""
BoundedSemaphore(有界信号量):
- 与Semaphore类似,但会检查释放次数
- 如果释放次数超过初始值,会抛出ValueError
- 防止因编程错误导致的计数器溢出
适用场景:
- 需要确保信号量正确释放的情况
- 调试和发现潜在问题
"""
BoundedSemaphore的使用:
import threading
def bounded_semaphore_demo():
"""BoundedSemaphore示例"""
# 创建有界信号量
semaphore = threading.BoundedSemaphore(2)
# 正确使用
with semaphore: #上下文管理器自动释放
print("First acquire")
with semaphore:
print("Second acquire")
# 错误使用(会抛出异常)
try:
semaphore.release()
semaphore.release() # 第二次release会抛出ValueError
print("Extra release succeeded")
except ValueError as e:
print(f"Error: {e}")
print("BoundedSemaphore demo finished")
# 使用示例
if __name__ == "__main__":
bounded_semaphore_demo()
4.5 asyncio异步编程基础
4.5.1 什么是asyncio?
asyncio的定义:
asyncio是Python 3.4引入的异步I/O库,用于编写并发代码,使用async/await语法。
asyncio的特点:
"""
asyncio的特点:
1. 单线程并发:在单个线程中实现并发
2. 事件循环:核心是事件循环机制
3. 协程:使用async/await定义协程
4. 非阻塞I/O:I/O操作不会阻塞事件循环
5. 高效:适合I/O密集型任务
优势:
1. 避免线程切换开销
2. 没有线程安全问题
3. 可以处理大量并发连接
4. 代码更简洁易读
适用场景:
1. 网络请求
2. 数据库操作
3. 文件I/O
4. WebSocket通信
"""
4.5.2 协程(Coroutine)
什么是协程?
"""
协程(Coroutine):
- 用户态的轻量级线程
- 由程序自己控制调度
- 可以暂停和恢复执行
- 比线程更轻量级
协程 vs 线程:
1. 协程由用户调度,线程由操作系统调度
2. 协程切换开销小,线程切换开销大
3. 协程没有线程安全问题
4. 协程适合I/O密集型任务
"""
定义和使用协程:
import asyncio
import time
async def simple_coroutine(name, delay):
"""简单的协程"""
print(f"Coroutine {name} started")
await asyncio.sleep(delay) # 模拟I/O操作
print(f"Coroutine {name} finished")
return f"Result {name}"
async def main():
"""主协程"""
print("=== Asyncio Coroutines ===")
start = time.time()
# 并发执行多个协程
results = await asyncio.gather(
simple_coroutine("A", 1),
simple_coroutine("B", 2),
simple_coroutine("C", 1)
)
end = time.time()
print(f"Total time: {end - start:.2f}s")
print(f"Results: {results}")
# 使用示例
if __name__ == "__main__":
asyncio.run(main())
async和await关键字:
import asyncio
async def demonstrate_async_await():
"""演示async和await"""
# async定义协程函数
async def async_function():
print("Async function started")
await asyncio.sleep(1)
print("Async function finished")
return "Done"
# await等待协程完成
result = await async_function()
print(f"Result: {result}")
# await只能在async函数中使用
# 普通函数中不能使用await
# 使用示例
if __name__ == "__main__":
asyncio.run(demonstrate_async_await())
4.5.3 事件循环
什么是事件循环?
"""
事件循环(Event Loop):
- asyncio的核心机制
- 调度和执行所有协程
- 处理I/O事件
- 管理定时器和回调
事件循环的工作流程:
1. 检查是否有就绪的任务
2. 执行就绪的任务
3. 处理I/O事件
4. 重复以上步骤
"""
事件循环的使用:
import asyncio
async def task(name, delay):
"""异步任务"""
print(f"Task {name} started")
await asyncio.sleep(delay)
print(f"Task {name} finished")
return f"Result {name}"
async def event_loop_demo():
"""事件循环示例"""
# 获取当前事件循环
loop = asyncio.get_running_loop()
print(f"Current loop: {loop}")
# 创建任务
task1 = asyncio.create_task(task("A", 1))
task2 = asyncio.create_task(task("B", 2))
# 等待任务完成
result1 = await task1
result2 = await task2
print(f"Results: {result1}, {result2}")
# 使用示例
if __name__ == "__main__":
asyncio.run(event_loop_demo()) #这里就已经创建了事件循环
'''
等价于:
创建一个事件循环
注册主协程任务
启动循环直到完成
关闭事件循环
'''
4.5.4 并发执行任务
使用asyncio.gather:
import asyncio
import time
async def fetch_data(name, delay):
"""获取数据"""
print(f"Fetching {name}...")
await asyncio.sleep(delay)
return f"Data {name}"
async def gather_demo():
"""asyncio.gather示例"""
print("=== asyncio.gather ===")
start = time.time()
# 并发执行多个协程
results = await asyncio.gather(
fetch_data("A", 1),
fetch_data("B", 2),
fetch_data("C", 1),
fetch_data("D", 1)
)
end = time.time()
print(f"Total time: {end - start:.2f}s")
print(f"Results: {results}")
# 使用示例
if __name__ == "__main__":
asyncio.run(gather_demo())
使用asyncio.wait:
import asyncio
import time
async def task(name, delay):
"""异步任务"""
print(f"Task {name} started")
await asyncio.sleep(delay)
print(f"Task {name} finished")
return f"Result {name}"
async def wait_demo():
"""asyncio.wait示例"""
print("=== asyncio.wait ===")
start = time.time()
# 创建任务
tasks = [
asyncio.create_task(task("A", 1)),
asyncio.create_task(task("B", 2)),
asyncio.create_task(task("C", 1))
]
# 等待所有任务完成
done, pending = await asyncio.wait(tasks)
end = time.time()
print(f"Total time: {end - start:.2f}s")
print(f"Done tasks: {len(done)}")
print(f"Pending tasks: {len(pending)}")
# 获取结果
results = [task.result() for task in done]
print(f"Results: {results}")
# 使用示例
if __name__ == "__main__":
asyncio.run(wait_demo())
使用asyncio.as_completed:
import asyncio
import time
async def task(name, delay):
"""异步任务"""
print(f"Task {name} started")
await asyncio.sleep(delay)
print(f"Task {name} finished")
return f"Result {name}"
async def as_completed_demo():
"""asyncio.as_completed示例"""
print("=== asyncio.as_completed ===")
start = time.time()
# 创建任务
tasks = [
asyncio.create_task(task("A", 1)),
asyncio.create_task(task("B", 3)),
asyncio.create_task(task("C", 2))
]
# 按完成顺序处理任务
for coro in asyncio.as_completed(tasks):
result = await coro
print(f"Completed: {result}")
end = time.time()
print(f"Total time: {end - start:.2f}s")
# 使用示例
if __name__ == "__main__":
asyncio.run(as_completed_demo())
4.5.5 超时控制
使用asyncio.wait_for:
import asyncio
async def slow_task():
"""慢速任务"""
print("Slow task started")
await asyncio.sleep(5)
print("Slow task finished")
return "Done"
async def timeout_demo():
"""超时控制示例"""
print("=== Timeout Control ===")
try:
# 设置3秒超时
result = await asyncio.wait_for(slow_task(), timeout=3.0)
print(f"Result: {result}")
except asyncio.TimeoutError:
print("Task timed out!")
# 使用示例
if __name__ == "__main__":
asyncio.run(timeout_demo())
使用asyncio.timeout(Python 3.11+):
import asyncio
async def task(name, delay):
"""异步任务"""
print(f"Task {name} started")
await asyncio.sleep(delay)
print(f"Task {name} finished")
return f"Result {name}"
async def timeout_context_manager_demo():
"""使用timeout上下文管理器"""
print("=== Timeout Context Manager ===")
try:
async with asyncio.timeout(2.0):
result = await task("A", 5)
print(f"Result: {result}")
except TimeoutError:
print("Task timed out!")
# 使用示例(需要Python 3.11+)
# if __name__ == "__main__":
# asyncio.run(timeout_context_manager_demo())
4.6 综合示例
4.6.1 实现一个并发HTTP请求工具
import asyncio
import aiohttp
import time
from typing import List, Dict
import logging
logging.basicConfig(level=logging.INFO)
class AsyncHTTPClient:
"""异步HTTP客户端"""
def __init__(self, max_concurrent: int = 10):
"""
初始化HTTP客户端
Args:
max_concurrent: 最大并发数
"""
self.max_concurrent = max_concurrent
self.semaphore = asyncio.Semaphore(max_concurrent)
async def fetch(
self,
session: aiohttp.ClientSession,
url: str,
method: str = "GET",
**kwargs
) -> Dict:
"""
发送HTTP请求
Args:
session: aiohttp会话
url: 请求URL
method: 请求方法
**kwargs: 其他请求参数
Returns:
Dict: 响应数据
"""
async with self.semaphore: # 限制并发数
try:
async with session.request(method, url, **kwargs) as response:
data = await response.text()
return {
"url": url,
"status": response.status,
"data": data
}
except Exception as e:
logging.error(f"Error fetching {url}: {e}")
return {
"url": url,
"error": str(e)
}
async def fetch_multiple(self, urls: List[str]) -> List[Dict]:
"""
并发获取多个URL
Args:
urls: URL列表
Returns:
List[Dict]: 响应列表
"""
async with aiohttp.ClientSession() as session:
tasks = [
self.fetch(session, url)
for url in urls
]
results = await asyncio.gather(*tasks)
return results
async def fetch_with_timeout(
self,
url: str,
timeout: float = 10.0
) -> Dict:
"""
带超时的HTTP请求
Args:
url: 请求URL
timeout: 超时时间
Returns:
Dict: 响应数据
"""
try:
async with asyncio.timeout(timeout):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
data = await response.text()
return {
"url": url,
"status": response.status,
"data": data
}
except asyncio.TimeoutError:
logging.error(f"Timeout fetching {url}")
return {
"url": url,
"error": "Timeout"
}
except Exception as e:
logging.error(f"Error fetching {url}: {e}")
return {
"url": url,
"error": str(e)
}
# 使用示例
async def http_client_demo():
"""HTTP客户端演示"""
client = AsyncHTTPClient(max_concurrent=5)
urls = [
"https://httpbin.org/get",
"https://httpbin.org/delay/1",
"https://httpbin.org/delay/2",
"https://httpbin.org/status/200",
"https://httpbin.org/status/404"
]
print("=== Fetching Multiple URLs ===")
start = time.time()
results = await client.fetch_multiple(urls)
end = time.time()
print(f"\nTotal time: {end - start:.2f}s")
print(f"Results: {len(results)} URLs")
for result in results:
if "error" in result:
print(f"✗ {result['url']}: {result['error']}")
else:
print(f"✓ {result['url']}: {result['status']}")
print("\n=== Fetching with Timeout ===")
result = await client.fetch_with_timeout("https://httpbin.org/delay/5", timeout=2)
print(f"Result: {result}")
# 运行示例
if __name__ == "__main__":
asyncio.run(http_client_demo())
4.6.2 实现一个并发DNS查询工具
import asyncio
import dns.asyncresolver
from typing import List, Dict, Set
import logging
logging.basicConfig(level=logging.INFO)
class AsyncDNSQuery:
"""异步DNS查询工具"""
def __init__(self, max_concurrent: int = 50):
"""
初始化DNS查询工具
Args:
max_concurrent: 最大并发数
"""
self.max_concurrent = max_concurrent
self.semaphore = asyncio.Semaphore(max_concurrent)
self.resolver = dns.asyncresolver.Resolver()
async def query_a_record(
self,
domain: str
) -> Dict:
"""
查询A记录
Args:
domain: 域名
Returns:
Dict: 查询结果
"""
async with self.semaphore:
try:
answers = await self.resolver.resolve(domain, 'A')
return {
"domain": domain,
"type": "A",
"records": [str(rdata) for rdata in answers],
"status": "success"
}
except dns.asyncresolver.NXDOMAIN:
return {
"domain": domain,
"type": "A",
"status": "not_found"
}
except Exception as e:
logging.error(f"Error querying {domain}: {e}")
return {
"domain": domain,
"type": "A",
"status": "error",
"error": str(e)
}
async def query_multiple(
self,
domains: List[str],
record_type: str = "A"
) -> List[Dict]:
"""
并发查询多个域名
Args:
domains: 域名列表
record_type: 记录类型
Returns:
List[Dict]: 查询结果列表
"""
if record_type == "A":
tasks = [self.query_a_record(domain) for domain in domains]
else:
# 可以扩展其他记录类型
tasks = [self.query_a_record(domain) for domain in domains]
results = await asyncio.gather(*tasks)
return results
async def scan_subdomains(
self,
domain: str,
subdomains: List[str]
) -> Dict:
"""
扫描子域名
Args:
domain: 主域名
subdomains: 子域名列表
Returns:
Dict: 扫描结果
"""
full_domains = [f"{sub}.{domain}" for sub in subdomains]
logging.info(f"Scanning {len(full_domains)} subdomains for {domain}")
results = await self.query_multiple(full_domains)
valid_subdomains = [
result["domain"]
for result in results
if result["status"] == "success"
]
return {
"domain": domain,
"total": len(full_domains),
"found": len(valid_subdomains),
"valid_subdomains": valid_subdomains,
"details": results
}
# 使用示例
async def dns_query_demo():
"""DNS查询演示"""
dns_query = AsyncDNSQuery(max_concurrent=10)
# 查询单个域名
print("=== Query Single Domain ===")
result = await dns_query.query_a_record("www.google.com")
print(f"Result: {result}")
# 查询多个域名
print("\n=== Query Multiple Domains ===")
domains = [
"www.google.com",
"www.github.com",
"www.python.org",
"nonexistent.example.com"
]
results = await dns_query.query_multiple(domains)
for result in results:
if result["status"] == "success":
print(f"✓ {result['domain']}: {result['records']}")
elif result["status"] == "not_found":
print(f"✗ {result['domain']}: Not found")
else:
print(f"✗ {result['domain']}: {result.get('error', 'Error')}")
# 扫描子域名
print("\n=== Scan Subdomains ===")
subdomains = [
"www", "mail", "ftp", "admin", "blog",
"api", "dev", "test", "staging", "m"
]
# 使用示例域名(实际使用时替换为目标域名)
# scan_result = await dns_query.scan_subdomains("example.com", subdomains)
# print(f"Found {scan_result['found']} valid subdomains")
# for subdomain in scan_result['valid_subdomains']:
# print(f" - {subdomain}")
# 运行示例
if __name__ == "__main__":
asyncio.run(dns_query_demo())
4.7 实践任务
任务1:实现多线程下载器
目标: 使用多线程实现一个文件下载器。
要求:
- 支持多个文件并发下载
- 显示下载进度
- 处理下载错误
- 限制最大并发数
- 使用线程池
代码框架:
import threading
import requests
from concurrent.futures import ThreadPoolExecutor
import os
class MultiThreadDownloader:
"""多线程下载器"""
def __init__(self, max_workers=5):
# 在这里实现你的代码
pass
def download_file(self, url, save_path):
# 在这里实现你的代码
pass
def download_multiple(self, urls, save_dir):
# 在这里实现你的代码
pass
# 使用示例
if __name__ == "__main__":
downloader = MultiThreadDownloader(max_workers=3)
urls = [
"https://example.com/file1.txt",
"https://example.com/file2.txt"
]
downloader.download_multiple(urls, "downloads")
任务2:实现线程安全的数据结构
目标: 实现线程安全的队列和计数器。
要求:
- 实现线程安全的FIFO队列
- 实现线程安全的计数器
- 实现线程安全的缓存
- 使用适当的锁机制
- 测试多线程环境下的正确性
代码框架:
import threading
from collections import deque
import time
class ThreadSafeQueue:
"""线程安全的队列"""
def __init__(self):
# 在这里实现你的代码
pass
def put(self, item):
# 在这里实现你的代码
pass
def get(self):
# 在这里实现你的代码
pass
def size(self):
# 在这里实现你的代码
pass
class ThreadSafeCounter:
"""线程安全的计数器"""
def __init__(self, initial=0):
# 在这里实现你的代码
pass
def increment(self):
# 在这里实现你的代码
pass
def decrement(self):
# 在这里实现你的代码
pass
def get_value(self):
# 在这里实现你的代码
pass
# 使用示例
if __name__ == "__main__":
# 测试你的线程安全数据结构
pass
任务3:实现异步HTTP爬虫
目标: 使用asyncio实现一个异步HTTP爬虫。
要求:
- 使用aiohttp发送HTTP请求
- 支持并发请求
- 限制最大并发数
- 处理超时和错误
- 保存爬取结果
代码框架:
import asyncio
import aiohttp
from typing import List, Dict
import time
class AsyncWebCrawler:
"""异步Web爬虫"""
def __init__(self, max_concurrent=10):
# 在这里实现你的代码
pass
async def fetch_page(self, url):
# 在这里实现你的代码
pass
async def crawl_multiple(self, urls):
# 在这里实现你的代码
pass
async def crawl_with_retry(self, url, max_retries=3):
# 在这里实现你的代码
pass
# 使用示例
if __name__ == "__main__":
async def main():
crawler = AsyncWebCrawler(max_concurrent=5)
urls = [
"https://example.com/page1",
"https://example.com/page2"
]
results = await crawler.crawl_multiple(urls)
print(results)
asyncio.run(main())
任务4:实现生产者消费者模型
目标: 使用多线程实现生产者消费者模型。
要求:
- 实现生产者线程
- 实现消费者线程
- 使用线程安全队列
- 控制生产和消费速度
- 正确处理线程结束
代码框架:
import threading
import queue
import time
import random
class ProducerConsumerModel:
"""生产者消费者模型"""
def __init__(self, max_size=10):
# 在这里实现你的代码
pass
def producer(self, name, items):
# 在这里实现你的代码
pass
def consumer(self, name):
# 在这里实现你的代码
pass
def start(self, num_producers, num_consumers):
# 在这里实现你的代码
pass
# 使用示例
if __name__ == "__main__":
model = ProducerConsumerModel(max_size=10)
model.start(num_producers=2, num_consumers=3)
任务5:综合实践
目标: 综合运用所学知识,实现一个并发工具。
要求:
- 实现一个并发任务调度器
- 支持多线程和异步两种模式
- 支持任务优先级
- 支持任务超时控制
- 支持任务重试机制
- 实现任务结果缓存
代码框架:
import asyncio
import threading
from concurrent.futures import ThreadPoolExecutor
from typing import Callable, Any, Dict
import time
class ConcurrentTaskScheduler:
"""并发任务调度器"""
def __init__(self, mode="async", max_workers=10):
# 在这里实现你的代码
pass
def submit_task(self, func, *args, priority=0, timeout=None, max_retries=0, **kwargs):
# 在这里实现你的代码
pass
async def run_async(self):
# 在这里实现你的代码
pass
def run_threaded(self):
# 在这里实现你的代码
pass
def get_results(self):
# 在这里实现你的代码
pass
# 使用示例
if __name__ == "__main__":
# 测试你的任务调度器
pass
4.8 本课总结
本课重点内容回顾
1. 进程与线程
- 进程的定义和特点
- 线程的定义和特点
- 多进程 vs 多线程的对比
- Python中的多进程和多线程实现
- 进程间通信和线程间共享数据
2. GIL机制
- GIL的定义和作用
- GIL对多线程的影响
- CPU密集型 vs I/O密集型任务
- 如何绕过GIL限制(多进程、C扩展、asyncio)
3. threading模块
- 创建和启动线程
- 线程属性和方法
- 守护线程
- 线程间通信(Queue、Event、Condition)
4. 线程同步与锁
- 竞争条件和线程安全问题
- Lock和RLock的使用
- Semaphore和BoundedSemaphore
- 超时获取锁
5. asyncio异步编程
- asyncio的基本概念
- 协程(async/await)
- 事件循环
- 并发执行任务(gather、wait、as_completed)
- 超时控制
下节课预告
第5课:OneForAll整体架构分析
- 项目整体设计
- 模块化架构
- 数据流和处理流程
- 配置管理系统
- 日志系统设计
- 入口文件解析
课后思考
- 为什么Python要引入GIL?GIL对程序性能有什么影响?
- 在什么情况下应该使用多线程,什么情况下应该使用多进程?
- asyncio相比多线程有什么优势?
- 如何避免死锁?
- 在OneForAll中,哪些部分适合使用多线程,哪些部分适合使用异步编程?
推荐阅读
- Python官方文档 - threading:https://docs.python.org/zh-cn/3/library/threading.html
- Python官方文档 - asyncio:https://docs.python.org/zh-cn/3/library/asyncio.html
- Python GIL详解:https://wiki.python.org/moin/GlobalInterpreterLock
- 并发编程实战:https://python-parallel-programmning-cookbook.readthedocs.io/
4.9 附录
附录A:线程安全速查表
"""
线程安全数据结构和方法:
1. Queue(线程安全队列)
- queue.Queue() - FIFO队列
- queue.LifoQueue() - LIFO队列
- queue.PriorityQueue() - 优先队列
- 方法:put(), get(), task_done(), join()
2. 锁
- threading.Lock() - 普通锁
- threading.RLock() - 可重入锁
- threading.Semaphore(n) - 信号量
- threading.BoundedSemaphore(n) - 有界信号量
3. 同步原语
- threading.Event() - 事件
- threading.Condition() - 条件变量
- threading.Barrier(n) - 屏障
4. 线程安全的数据结构
- queue.Queue
- collections.deque(部分操作需要加锁)
- threading.local() - 线程局部存储
"""
附录B:asyncio速查表
"""
asyncio常用函数和类:
1. 协程定义和执行
- async def func(): await something
- asyncio.run(coro) - 运行协程
- asyncio.create_task(coro) - 创建任务
2. 并发执行
- asyncio.gather(*coros) - 并发执行多个协程
- asyncio.wait(tasks) - 等待任务完成
- asyncio.as_completed(tasks) - 按完成顺序处理
3. 超时控制
- asyncio.wait_for(coro, timeout) - 带超时的等待
- async with asyncio.timeout(n): - 超时上下文
4. 同步原语
- asyncio.Lock() - 异步锁
- asyncio.Event() - 异步事件
- asyncio.Semaphore(n) - 异步信号量
- asyncio.Condition() - 异步条件变量
5. 队列
- asyncio.Queue() - 异步队列
- asyncio.LifoQueue() - 异步LIFO队列
- asyncio.PriorityQueue() - 异步优先队列
"""
附录C:并发模式速查表
"""
常见并发模式:
1. 生产者-消费者模式
- 使用Queue进行通信
- 生产者放入数据,消费者取出数据
- 适用于解耦生产和消费
2. 线程池模式
- 使用ThreadPoolExecutor
- 复用线程,减少创建开销
- 限制最大并发数
3. Future模式
- 使用concurrent.futures.Future
- 异步获取任务结果
- 支持回调函数
4. 资源池模式
- 使用Semaphore限制并发
- 管理有限资源
- 如数据库连接池
5. Pipeline模式
- 数据分阶段处理
- 每个阶段由不同线程/协程处理
- 提高吞吐量
"""
附录D:学习检查清单
恭喜你完成了第4课的学习!🎉
现在你已经掌握了并发编程的基础知识,包括进程与线程、GIL机制、threading模块、线程同步、asyncio异步编程等。这些都是开发OneForAll高性能并发处理功能所必需的技能。
在下一课中,我们将深入学习OneForAll的整体架构,理解项目的设计思想和实现原理。
记住: 并发编程是实践性很强的技能,一定要动手完成所有的实践任务!
继续加油,我们下节课见!💪

浙公网安备 33010602011771号