面试题答案
一键面试1. 安全且高效检查条件的方法
在Python多线程环境下,为了安全且高效地检查涉及共享数据状态的条件,可以使用锁(Lock
)、条件变量(Condition
)等同步机制。
2. 代码示例
import threading
import time
# 共享数据
shared_list = []
shared_dict = {}
lock = threading.Lock()
condition = threading.Condition(lock)
def worker1():
global shared_list
with lock:
for i in range(5):
shared_list.append(i)
condition.notify_all() # 通知其他线程共享数据已更新
time.sleep(1)
def worker2():
global shared_dict
with lock:
for i in range(5):
shared_dict[f'key_{i}'] = i
condition.notify_all() # 通知其他线程共享数据已更新
time.sleep(1)
def main_thread():
with lock:
while True:
# 检查共享列表长度变化
if len(shared_list) >= 3:
print(f"共享列表长度达到3,当前长度: {len(shared_list)}")
# 检查共享字典特定键值对更新
if 'key_2' in shared_dict and shared_dict['key_2'] == 2:
print("共享字典中key_2的值已更新为2")
condition.wait(timeout=1) # 等待数据更新通知,设置超时防止死等
if len(shared_list) >= 5 and len(shared_dict) >= 5:
break
if __name__ == "__main__":
t1 = threading.Thread(target=worker1)
t2 = threading.Thread(target=worker2)
t1.start()
t2.start()
main_thread()
t1.join()
t2.join()
3. 可能遇到的并发问题及解决方案
- 竞态条件(Race Condition):多个线程同时访问和修改共享数据,导致数据不一致。解决方案是使用锁(
Lock
),确保同一时间只有一个线程可以访问共享数据。 - 死锁(Deadlock):两个或多个线程相互等待对方释放资源,导致程序无法继续执行。为避免死锁,要合理安排锁的获取顺序,避免嵌套锁,并且尽量缩短持有锁的时间。
- 活锁(Livelock):线程不断重试相同的操作,但由于其他线程也在同时进行操作,导致没有线程能取得进展。解决方案是在重试操作中引入随机延迟,避免线程间的持续冲突。
- 饥饿(Starvation):某个线程由于其他线程频繁获取资源,而长时间无法获取到所需资源。可以通过公平调度算法,例如使用
Condition
的acquire
方法的timeout
参数,设置等待时间,防止某个线程长时间等待。