Python实现互斥锁和条件变量
在并发编程中,多个线程同时访问共享数据时可能会产生竞态条件(race condition),导致程序出现不可预料的结果。为了解决这个问题,Python提供了互斥锁和条件变量这两种同步机制。
互斥锁
互斥锁(mutex)是一种用于保护共享资源的同步原语。在任意时刻,只有一个线程能够持有互斥锁,并且其他线程必须等待该线程释放锁之后才能继续执行。
在Python中,可以使用threading
模块中的Lock
类来创建互斥锁。下面是一个使用互斥锁的示例代码:
import threading
# 创建互斥锁
lock = threading.Lock()
# 共享资源
counter = 0
# 线程函数
def worker():
global counter
with lock: # 通过with语句获取锁
for _ in range(100000):
counter += 1
# 创建多个线程并启动
threads = []
for _ in range(10):
t = threading.Thread(target=worker)
threads.append(t)
t.start()
# 等待所有线程执行完毕
for t in threads:
t.join()
# 打印最终结果
print("Counter:", counter)
在上面的代码中,我们首先创建了一个互斥锁lock
。然后定义了一个共享资源counter
,它被多个线程同时访问和修改。在worker
函数中,我们使用了with lock
语句来获取互斥锁。这样一来,每个线程在执行with lock
语句块中的代码之前都会尝试获取锁,如果锁已经被其他线程占用,则会被阻塞等待。
最后,我们创建了多个线程并启动它们,然后使用join
方法等待所有线程执行完毕。最终,输出的结果应该是Counter: 1000000
。由于互斥锁的存在,共享资源在被多个线程访问时能够保持一致性。
条件变量
条件变量(condition variable)是一种用于线程间通信的同步原语。它提供了一个线程等待某个条件成立的机制,并且能够在条件变量的状态发生变化时通知等待的线程。
在Python中,可以使用threading
模块中的Condition
类来创建条件变量。下面是一个使用条件变量的示例代码:
import threading
# 创建条件变量
condition = threading.Condition()
# 共享资源
buffer = []
buffer_size = 5
# 生产者线程函数
def producer():
while True:
with condition:
# 如果缓冲区已满,则等待消费者消费
while len(buffer) == buffer_size:
condition.wait()
# 生产一个数据并放入缓冲区
item = len(buffer) + 1
buffer.append(item)
print("Produced:", item)
condition.notify_all() # 通知消费者消费
# 消费者线程函数
def consumer():
while True:
with condition:
# 如果缓冲区为空,则等待生产者生产
while len(buffer) == 0:
condition.wait()
# 从缓冲区取出一个数据并消费
item = buffer.pop(0)
print("Consumed:", item)
condition.notify_all() # 通知生产者生产
# 创建生产者线程并启动
t1 = threading.Thread(target=producer)
t1.start()
# 创建消费者线程并启动
t2 = threading.Thread(target=consumer)
t2.start()
# 等待生产者和消费者线程执行完毕
t1.join()
t2.join()
在上面的代码中,我们首先创建了一个条件变量condition
。然后定义了一个共享资源buffer
,它被生产者线程往里面放入数据,消费者线程从里面取出数据。缓冲区的最大大小由buffer_size
指