[英]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.