Skip to content

Commit a0374dd

Browse files
vitiralasvetlov
authored andcommitted
bpo-32208: update threading.Semaphore docs and add unit test (#4709)
* fix issue32208: update threading.Semaphore docs and add unit test to validate correct behavior * add test for blocking * Update threading.rst * semaphore: remove documentation validation tests and move 'return value' test to BaseSemaphore
1 parent 961dbe0 commit a0374dd

File tree

2 files changed

+17
-15
lines changed

2 files changed

+17
-15
lines changed

Doc/library/threading.rst

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,8 @@ Semaphores also support the :ref:`context management protocol <with-locks>`.
684684

685685
.. class:: Semaphore(value=1)
686686

687-
This class implements semaphore objects. A semaphore manages a counter
688-
representing the number of :meth:`release` calls minus the number of
687+
This class implements semaphore objects. A semaphore manages an atomic
688+
counter representing the number of :meth:`release` calls minus the number of
689689
:meth:`acquire` calls, plus an initial value. The :meth:`acquire` method
690690
blocks if necessary until it can return without making the counter negative.
691691
If not given, *value* defaults to 1.
@@ -701,19 +701,19 @@ Semaphores also support the :ref:`context management protocol <with-locks>`.
701701

702702
Acquire a semaphore.
703703

704-
When invoked without arguments: if the internal counter is larger than
705-
zero on entry, decrement it by one and return immediately. If it is zero
706-
on entry, block, waiting until some other thread has called
707-
:meth:`~Semaphore.release` to make it larger than zero. This is done
708-
with proper interlocking so that if multiple :meth:`acquire` calls are
709-
blocked, :meth:`~Semaphore.release` will wake exactly one of them up.
710-
The implementation may pick one at random, so the order in which
711-
blocked threads are awakened should not be relied on. Returns
712-
true (or blocks indefinitely).
704+
When invoked without arguments:
705+
706+
* If the internal counter is larger than zero on entry, decrement it by
707+
one and return true immediately.
708+
* If the internal counter is zero on entry, block until awoken by a call to
709+
:meth:`~Semaphore.release`. Once awoken (and the counter is greater
710+
than 0), decrement the counter by 1 and return true. Exactly one
711+
thread will be awoken by each call to :meth:`~Semaphore.release`. The
712+
order in which threads are awoken should not be relied on.
713713

714714
When invoked with *blocking* set to false, do not block. If a call
715-
without an argument would block, return false immediately; otherwise,
716-
do the same thing as when called without arguments, and return true.
715+
without an argument would block, return false immediately; otherwise, do
716+
the same thing as when called without arguments, and return true.
717717

718718
When invoked with a *timeout* other than ``None``, it will block for at
719719
most *timeout* seconds. If acquire does not complete successfully in

Lib/test/lock_tests.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,13 +629,14 @@ def test_acquire_contended(self):
629629
sem = self.semtype(7)
630630
sem.acquire()
631631
N = 10
632+
sem_results = []
632633
results1 = []
633634
results2 = []
634635
phase_num = 0
635636
def f():
636-
sem.acquire()
637+
sem_results.append(sem.acquire())
637638
results1.append(phase_num)
638-
sem.acquire()
639+
sem_results.append(sem.acquire())
639640
results2.append(phase_num)
640641
b = Bunch(f, 10)
641642
b.wait_for_started()
@@ -659,6 +660,7 @@ def f():
659660
# Final release, to let the last thread finish
660661
sem.release()
661662
b.wait_for_finished()
663+
self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1))
662664

663665
def test_try_acquire(self):
664666
sem = self.semtype(2)

0 commit comments

Comments
 (0)