Skip to content

Commit a04ca12

Browse files
miss-islingtonasvetlov
authored andcommitted
bpo-32208: update threading.Semaphore docs and add unit test (GH-4709) (#4750)
* 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 (cherry picked from commit a0374dd)
1 parent 03031fb commit a04ca12

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
@@ -619,13 +619,14 @@ def test_acquire_contended(self):
619619
sem = self.semtype(7)
620620
sem.acquire()
621621
N = 10
622+
sem_results = []
622623
results1 = []
623624
results2 = []
624625
phase_num = 0
625626
def f():
626-
sem.acquire()
627+
sem_results.append(sem.acquire())
627628
results1.append(phase_num)
628-
sem.acquire()
629+
sem_results.append(sem.acquire())
629630
results2.append(phase_num)
630631
b = Bunch(f, 10)
631632
b.wait_for_started()
@@ -649,6 +650,7 @@ def f():
649650
# Final release, to let the last thread finish
650651
sem.release()
651652
b.wait_for_finished()
653+
self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1))
652654

653655
def test_try_acquire(self):
654656
sem = self.semtype(2)

0 commit comments

Comments
 (0)