在Python中,线程同步可以通过threading.Lock对象来实现。下面是一个使用threading.Lock来确保多线程访问共享资源互斥的示例:
import threading
import time
# 共享资源
shared_resource = 0
# 创建一个Lock对象
lock = threading.Lock()
def worker_thread(id):
global shared_resource
# 在修改共享资源之前获取锁
lock.acquire()
try:
print(f"线程 {id} 开始访问共享资源")
# 模拟耗时操作,如IO或计算
time.sleep(1)
# 修改共享资源
shared_resource += 1
print(f"线程 {id} 结束访问并更新了共享资源,当前值为:{shared_resource}")
finally:
# 访问结束后释放锁,允许其他线程获取
lock.release()
# 创建两个线程
threads = []
for i in range(2):
thread = threading.Thread(target=worker_thread, args=(i,))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print("所有线程已完成,最终共享资源的值应为2")
在这个例子中,threading.Lock()创建了一个锁对象。当多个线程尝试访问共享资源(这里是变量shared_resource)时,每个线程都会先调用lock.acquire()来获取锁。如果锁已被另一个线程持有,则该线程会阻塞,直到锁被释放。在try/finally块中确保无论发生什么情况,最后都会通过lock.release()释放锁,以保证其他线程能够继续访问共享资源。
- 下面我们实现一个简单的生产者-消费者模式,使用threading.Lock实现生产者-消费者模式时,可以确保同一时间只有一个线程(生产者或消费者)访问共享资源(例如,一个队列)。下面是一个简单的示例,其中生产者将数字放入队列,并且消费者从队列中取出并打印数字。这里我们用列表作为简单的队列,并使用锁和条件变量来同步生产与消费:
import threading
import random
import time
# 共享资源:队列和锁
queue = []
max_queue_size = 10
lock = threading.Lock()
not_full = threading.Condition(lock) # 当队列未满时通知生产者
not_empty = threading.Condition(lock) # 当队列非空时通知消费者
def producer(id, total_items):
global queue
for _ in range(total_items):
not_full.acquire() # 获取锁并等待队列不满
while len(queue) == max_queue_size:
print(f"生产者{id}:队列已满,等待消费者消耗...")
not_full.wait()
item = random.randint(1, 100)
queue.append(item)
print(f"生产者{id} 生产了商品 {item},当前队列长度: {len(queue)}")
not_empty.notify() # 通知消费者队列中有新的元素
not_full.release() # 释放锁
def consumer(id):
global queue
while True:
not_empty.acquire() # 获取锁并等待队列不为空
while not queue:
print(f"消费者{id}:队列为空,等待生产者生产...")
not_empty.wait()
item = queue.pop(0)
print(f"消费者{id} 消费了商品 {item},当前队列长度: {len(queue)}")
not_full.notify() # 告知生产者队列有空间可放新元素
not_empty.release() # 释放锁
# 创建并启动生产者和消费者线程
producer_threads = [threading.Thread(target=producer, args=(i, 5)) for i in range(2)]
consumer_thread = threading.Thread(target=consumer, args=(1,))
for thread in producer_threads:
thread.start()
consumer_thread.start()
# 等待所有线程完成
for thread in producer_threads:
thread.join()
consumer_thread.join()
print("所有生产者和消费者已完成任务")
在这个例子中,生产者通过not_full条件变量等待队列不满,然后添加产品到队列,并唤醒等待的消费者。消费者则通过not_empty条件变量等待队列非空,然后从队列中取出并消费产品,并唤醒等待的生产者。通过这种方式,生产者和消费者之间实现了有效的同步,避免了并发访问队列时的数据竞争问题。