multiprocessing.Semaphore 和 multiprocessing.BoundedSemaphore 有什么区别?

What is the difference between multiprocessing.Semaphore and multiprocessing.BoundedSemaphore?

multiprocessing.BoundedSemaphore(3)multiprocessing.Sempahore(3) 有何不同?

我希望 multiprocessing.BoundedSemaphore(3) 永远不会允许其内部计数器值超过 3。

据此我得出结论,即使我获取此信号量的进程最终错误地多次释放信号量(比如获取一次但释放五次),它也不会允许超过 3 个进程在任何时间点获取信号量。然而,我的这个结论似乎是不正确的。

这是我的 Python 示例代码,位于名为 multi.py.

的文件中
#!/usr/bin/env python
import multiprocessing
import time

def f(i, sem):
    print 'f(%d) acquiring ...' % i
    sem.acquire()
    print 'f(%d) acquired' % i

    time.sleep(i + 1)

    print 'f(%d) releasing ...' % i
    sem.release()
    sem.release() # Extra release on purpose
    sem.release() # Extra release on purpose
    sem.release() # Extra release on purpose
    sem.release() # Extra release on purpose
    print 'f(%d) released' % i

processes = []

sem = multiprocessing.BoundedSemaphore(3)
for i in range(10):
    p = multiprocessing.Process(target=f, args=(i, sem))
    p.start()
    processes.append(p)

for p in processes:
    p.join()

print 'Done'

这是我的 macOS Sierra 10.12.5 和 Python 2.7.13 的输出。下面输出之间的空行是我手动插入的,以指示输出之间的暂停。

$ ./multi.py                                                                                                                                                                            [56/1853]
f(0) acquiring ...
f(0) acquired
f(1) acquiring ...
f(1) acquired
f(2) acquiring ...
f(2) acquired
f(3) acquiring ...
f(4) acquiring ...
f(5) acquiring ...
f(6) acquiring ...
f(7) acquiring ...
f(8) acquiring ...
f(9) acquiring ...

f(0) releasing ...
f(0) released
f(3) acquired
f(5) acquired
f(4) acquired
f(6) acquired
f(7) acquired

f(1) releasing ...
f(1) released
f(9) acquired
f(8) acquired

f(2) releasing ...
f(2) released

f(3) releasing ...
f(3) released

f(4) releasing ...
f(4) released

f(5) releasing ...
f(5) released

f(6) releasing ...
f(6) released

f(7) releasing ...
f(7) released

f(8) releasing ...
f(8) released

f(9) releasing ...
f(9) released
Done

以上输出显示 f(0)f(1)f(2) 获取有界信号量,其余进程在尝试获取时阻塞,表明有界信号量的内部计数器信号量现在降为 0。

然后f(0)释放有界信号量5次。在此之后,我期望有界信号量的内部计数器为 3(因为它是有界的),所以现在应该还有 3 个进程能够获取有界信号量。但是从输出来看,有界信号量的内部计数器似乎已增加到 5,因为有 5 个进程获取了有界信号量。获取有界信号量的 5 个进程是 f(3)f(5)f(4)f(7)f(7).

如果一个multiprocessing.BoundedSemaphore对象的内部计数器有可能超过初始值,那么它和multiprocessing.Semaphore有什么不同?

来自 Python 关于 BoundedSemaphore 的 2.7 文档:

Note On Mac OS X, this is indistinguishable from Semaphore because sem_getvalue() is not implemented on that platform.

https://docs.python.org/2/library/multiprocessing.html#synchronization-primitives