线程间共享数据同步机制
- 锁(
Lock
):
- 适用场景:当需要保护共享资源,确保同一时间只有一个线程能访问该资源时使用。例如,多个线程同时操作一个全局变量,防止数据竞争。
- 使用示例:
import threading
# 创建锁
lock = threading.Lock()
shared_variable = 0
def increment():
global shared_variable
with lock:
shared_variable += 1
- 信号量(
Semaphore
):
- 适用场景:当需要限制同时访问共享资源的线程数量时使用。比如,限制同时访问数据库连接池中的连接数量。
- 使用示例:
import threading
# 创建信号量,允许最多3个线程同时访问
semaphore = threading.Semaphore(3)
def access_resource():
with semaphore:
# 访问共享资源的代码
pass
- 队列(
Queue
):
- 适用场景:在线程间传递数据时非常有用,它是线程安全的。可以用于生产者 - 消费者模式,避免数据竞争。
- 使用示例:
import threading
import queue
# 创建队列
q = queue.Queue()
def producer():
for i in range(5):
q.put(i)
def consumer():
while True:
item = q.get()
if item is None:
break
# 处理数据
print(f"Consumed {item}")
q.task_done()
进程间数据交互与同步机制
- 锁(
multiprocessing.Lock
):
- 适用场景:与线程锁类似,用于保护进程间共享资源,防止数据竞争。例如,多个进程同时写入一个文件。
- 使用示例:
import multiprocessing
# 创建锁
lock = multiprocessing.Lock()
shared_value = multiprocessing.Value('i', 0)
def increment_process():
global shared_value
with lock:
shared_value.value += 1
- 信号量(
multiprocessing.Semaphore
):
- 适用场景:限制同时访问共享资源的进程数量,例如限制同时访问系统硬件资源的进程数。
- 使用示例:
import multiprocessing
# 创建信号量,允许最多2个进程同时访问
semaphore = multiprocessing.Semaphore(2)
def access_shared_resource():
with semaphore:
# 访问共享资源的代码
pass
- 队列(
multiprocessing.Queue
):
- 适用场景:用于进程间安全地传递数据,是进程安全的。常用于进程间的生产者 - 消费者模式。
- 使用示例:
import multiprocessing
# 创建队列
q = multiprocessing.Queue()
def producer_process():
for i in range(5):
q.put(i)
def consumer_process():
while True:
item = q.get()
if item is None:
break
# 处理数据
print(f"Consumed {item}")
q.task_done()
- 管道(
multiprocessing.Pipe
):
- 适用场景:用于两个进程之间进行数据通信,提供了一个双向的通信通道。
- 使用示例:
import multiprocessing
def sender(conn):
conn.send('Hello from sender')
conn.close()
def receiver(conn):
message = conn.recv()
print(f"Received: {message}")
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = multiprocessing.Pipe()
p1 = multiprocessing.Process(target = sender, args=(child_conn,))
p2 = multiprocessing.Process(target = receiver, args=(parent_conn,))
p1.start()
p2.start()
p1.join()
p2.join()
避免死锁
- 死锁原因:死锁通常发生在多个线程或进程相互等待对方释放资源的情况下。例如,线程A持有资源1并等待资源2,而线程B持有资源2并等待资源1。
- 避免方法:
- 按顺序获取锁:确保所有线程或进程以相同的顺序获取锁。例如,如果有锁
lock1
和lock2
,所有线程都先获取lock1
,再获取lock2
。
- 使用超时机制:在获取锁时设置超时时间,如果在超时时间内未能获取锁,则放弃获取并进行其他处理。例如,
lock.acquire(timeout = 5)
表示尝试获取锁,如果5秒内未获取到则返回False
。
- 减少锁的持有时间:尽量缩短线程或进程持有锁的时间,尽快释放锁,让其他线程或进程有机会获取。