跳转至

Python信号量

在 Python 中,信号量(Semaphore)是一种同步原语,用于管理并发访问的资源。信号量维护一个内部计数器,该计数器表示还剩余多少资源可供使用。当需要使用资源时,线程可以尝试获取信号量,如果信号量计数大于零,则减少计数并允许访问资源;如果计数为零,则线程需要等待直到有资源可用或超时。下面详细介绍 Python 中信号量的使用方法。

1. 使用 threading.Semaphore

Python 提供了 threading 模块,其中的 Semaphore 类用于创建信号量对象。主要方法包括:

  • acquire():尝试获取信号量。如果信号量计数大于零,则计数减一并立即返回;如果计数为零,则阻塞直到有资源可用。
  • release():释放信号量。增加信号量计数,通常在使用完资源后调用。

示例

import threading
import time

# 创建信号量对象,设置初始计数为2
semaphore = threading.Semaphore(2)

def access_resource(name):
    print(f"{name} is trying to access")
    semaphore.acquire()
    print(f"{name} is accessing the resource")
    time.sleep(2)  # 模拟访问资源
    print(f"{name} is releasing")
    semaphore.release()

# 创建多个线程访问资源
thread1 = threading.Thread(target=access_resource, args=("Thread 1",))
thread2 = threading.Thread(target=access_resource, args=("Thread 2",))
thread3 = threading.Thread(target=access_resource, args=("Thread 3",))

thread1.start()
thread2.start()
thread3.start()

thread1.join()
thread2.join()
thread3.join()

输出结果可能类似于:

Thread 1 is trying to access
Thread 1 is accessing the resource
Thread 2 is trying to access
Thread 2 is accessing the resource
Thread 1 is releasing
Thread 3 is trying to access
Thread 3 is accessing the resource
Thread 2 is releasing
Thread 3 is releasing

2. 使用 asyncio.Semaphore(异步)

在异步编程中,可以使用 asyncio 模块提供的 Semaphore 类来实现类似的功能。Semaphore 对象与 threading.Semaphore 类似,但是适用于协程而非线程。

示例

import asyncio

# 创建信号量对象,设置初始计数为2
semaphore = asyncio.Semaphore(2)

async def access_resource(name):
    print(f"{name} is trying to access")
    async with semaphore:
        print(f"{name} is accessing the resource")
        await asyncio.sleep(2)  # 模拟访问资源
        print(f"{name} is releasing")

# 创建多个协程访问资源
async def main():
    tasks = [access_resource(f"Coroutine {i}") for i in range(3)]
    await asyncio.gather(*tasks)

# 运行事件循环
asyncio.run(main())

输出结果可能类似于:

Coroutine 0 is trying to access
Coroutine 0 is accessing the resource
Coroutine 1 is trying to access
Coroutine 1 is accessing the resource
Coroutine 0 is releasing
Coroutine 2 is trying to access
Coroutine 2 is accessing the resource
Coroutine 1 is releasing
Coroutine 2 is releasing

3. 总结

信号量在多线程和异步编程中都是非常有用的同步工具,可以有效地管理并发访问的资源,避免竞态条件和资源争用问题。在编写并发程序时,根据需要选择合适的信号量类(threading.Semaphoreasyncio.Semaphore),并正确使用其 acquire()release() 方法来确保程序的正确性和效率。

评论