繁体   English   中英

在 python 中订购了 semaphore.aquire()

[英]Ordered semaphore.aquire() in python

我有多个multiprocessing.Process()获取和释放:

s = Semaphore(5)

s.acquire()调用是否保证按顺序完成?

如果没有,我可以使用什么来代替第一个请求进程首先访问资源?

根据threading.Semaphore.acquire文档

如果进入时内部计数器大于零,则将其减一并立即返回 True。
如果进入时内部计数器为零,则阻塞直到被调用 release() 唤醒。 一旦被唤醒(并且计数器大于 0),将计数器减 1 并返回 True。 每次调用 release() 都会唤醒一个线程。 不应依赖唤醒线程的顺序。

(强调我的)

换句话说,当你的信号量还没有达到零时,调用会立即成功。 然后,所有调用都会阻塞,直到调用一个release 此时,任何线程都可以从它的acquire中返回。

这是一个最小的可重现示例

import threading

NB_TOTAL = 20
NB_SHARED = 5

sem = threading.Semaphore(5)


def acquire_semaphore_then_do_something(thread_number: int):
    sem.acquire()
    do_something(thread_number)
    sem.release()


def do_something(number: int):
    print(number)


# create the threads
threads = [threading.Thread(target=acquire_semaphore_then_do_something, args=(thread_number,))
           for thread_number in range(NB_TOTAL)]
# start them all
for thread in threads:
    thread.start()
# wait for all of them to finish
for thread in threads:
    thread.join()

如果你真的需要线程完全按照它们创建的顺序运行,我建议以不同的方式处理事情:

import threading

NB_TOTAL = 20
NB_SHARED = 5

THREAD_LOCKS = [threading.Lock() for _ in range(NB_TOTAL)]
LOCKS_LOCK = threading.Lock()  # lock for the locks management
NEXT_UNLOCK_INDEX = NB_SHARED


def acquire_sequentially_then_do_something(thread_number: int):
    # try to acquire the dedicated lock
    THREAD_LOCKS[thread_number].acquire()  # blocking
    # dedicated lock acquired, proceeding
    do_something(thread_number)
    # now it has finished its work, it can unlock the next thread
    global NEXT_UNLOCK_INDEX
    if NEXT_UNLOCK_INDEX < NB_TOTAL:
        with LOCKS_LOCK:
            THREAD_LOCKS[NEXT_UNLOCK_INDEX].release()
            NEXT_UNLOCK_INDEX += 1


def do_something(number: int):
    print(number)


# lock all the locks, except the NB_SHARED first : indexes from 0 to NB_SHARED-1
for number, lock in enumerate(THREAD_LOCKS):
    if number >= NB_SHARED:
        assert lock.acquire(blocking=False)
# create the threads
threads = [threading.Thread(target=acquire_sequentially_then_do_something, args=(thread_number,))
           for thread_number in range(NB_TOTAL)]
# start them all
for thread in threads:
    thread.start()
# wait for all of them to finish
for thread in threads:
    thread.join()

正确打印

0
1
2
[...]
17
18
19

思路是NEXT_UNLOCK_INDEX会 1 加 1,每次解锁特定的锁,这样对应的线程才能最终锁定它并继续。 它确保线程遵守“先到先服务”的原则。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM