MST

星途 面试题库

面试题:Python中如何使用信号量(Semaphore)预防多线程死锁?

假设你正在开发一个Python多线程应用,其中多个线程需要访问有限数量的资源。请详细说明如何利用信号量(Semaphore)来预防死锁,并且给出具体的代码实现,代码需要展示多个线程对资源的竞争访问以及信号量的控制逻辑。
31.9万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

1. 信号量预防死锁原理

在多线程编程中,死锁通常发生在多个线程互相等待对方释放资源的情况下。信号量可以用来控制同时访问资源的线程数量。通过合理分配信号量,使得线程在获取资源前先获取信号量,使用完资源后释放信号量,避免多个线程同时获取所有资源,从而预防死锁。

2. 代码实现

import threading
import time


# 假设这是有限数量的资源
resource_count = 3
# 创建信号量,初始值为资源数量
semaphore = threading.Semaphore(resource_count)


def worker(worker_id):
    print(f"Worker {worker_id} 尝试获取资源")
    # 获取信号量,如果信号量为0,线程会阻塞直到有信号量可用
    semaphore.acquire()
    try:
        print(f"Worker {worker_id} 获取到资源,开始工作")
        # 模拟工作
        time.sleep(2)
        print(f"Worker {worker_id} 工作完成,释放资源")
    finally:
        # 释放信号量,让其他线程有机会获取
        semaphore.release()


# 创建多个线程
threads = []
for i in range(5):
    t = threading.Thread(target=worker, args=(i,))
    threads.append(t)
    t.start()


# 等待所有线程完成
for t in threads:
    t.join()

3. 代码解释

  1. 信号量创建semaphore = threading.Semaphore(resource_count) 创建了一个信号量对象,初始值为 resource_count,即资源的数量。
  2. 获取信号量:在 worker 函数中,semaphore.acquire() 用于获取信号量。如果当前信号量的值大于0,信号量的值减1,线程继续执行;如果信号量的值为0,线程会被阻塞,直到有其他线程释放信号量。
  3. 释放信号量:在 try - finally 块中,semaphore.release() 用于释放信号量,将信号量的值加1,让其他线程有机会获取信号量。
  4. 多线程创建与启动:通过循环创建多个线程,并启动它们。每个线程都会尝试获取信号量来访问资源,从而展示了多个线程对资源的竞争访问以及信号量的控制逻辑。