设计思路
- 上下文管理器:使用
contextlib.contextmanager
装饰器创建上下文管理器,在进入上下文时获取锁,离开上下文时释放锁,以此来确保共享资源在同一时间只有一个线程能访问。
- 装饰器:利用上下文管理器,在被装饰函数执行前进入上下文(获取锁),执行后离开上下文(释放锁),从而防止多线程环境下对共享资源的资源竞争。
代码实现
import threading
import contextlib
@contextlib.contextmanager
def resource_lock():
lock = threading.Lock()
lock.acquire()
try:
yield
finally:
lock.release()
def thread_safe_resource_operation(func):
def wrapper(*args, **kwargs):
with resource_lock():
return func(*args, **kwargs)
return wrapper
# 模拟文件操作的共享资源函数
@thread_safe_resource_operation
def file_operation():
print("Performing file operation...")
# 测试多线程环境
threads = []
for _ in range(5):
t = threading.Thread(target=file_operation)
threads.append(t)
t.start()
for t in threads:
t.join()
防止资源竞争的原理
- 锁机制:
threading.Lock
是线程锁,在任何时刻只有一个线程可以获得锁。当一个线程获取锁后,其他线程尝试获取锁时会被阻塞,直到该线程释放锁。
- 上下文管理器:通过
resource_lock
上下文管理器,确保在进入with
语句块时获取锁,离开with
语句块时释放锁,这样就保证了在with
语句块内的代码(即共享资源操作部分)同一时间只有一个线程在执行。
- 装饰器:
thread_safe_resource_operation
装饰器将被装饰函数的执行部分包裹在with resource_lock()
语句块内,从而使得被装饰的共享资源操作函数在多线程环境下可以安全执行,避免资源竞争。