Title: Theory / Unimportant / CS / Programming / Python / Async / Lock
On every note of this deck, unless a note says otherwise:
Page: https://docs.python.org/3.10/library/asyncio-sync.html
Page: https://docs.python.org/3.10/library/asyncio-sync.html

Question: Difference between asyncio synchronization and threading
Answer: asyncio primitives are not thread-safe, therefore they should not be used for OS thread synchronization (use threading for that);
Page: https://docs.python.org/3.10/library/asyncio-sync.html
Context: python
Answer2: methods of these synchronization primitives do not accept the timeout argument; use the asyncio.wait_for() function to perform operations with timeouts.

Typ: asyncio.Lock
Meaning: Implements a mutex lock for asyncio tasks. Not thread-safe.
Language: python

Typ: asyncio.Event
Meaning: An event object.
Language: python

Typ: asyncio.Condition
Meaning: primitive that can be used by a task to wait for some event to happen and then get exclusive access to a shared resource.
Language: python
Intuition: a Condition object combines the functionality of an Event and a Lock. It is possible to have multiple Condition objects share one Lock, which allows coordinating exclusive access to a shared resource between different tasks interested in particular states of that shared resource.

Typ: asyncio.Semaphore
Meaning: manages an internal counter which is decremented by each acquire() call and incremented by each release() call. The counter can never go below zero; when acquire() finds that it is zero, it blocks, waiting until some task calls release() .
Language: python

Typ: asyncio.BoundedSemaphore
Meaning: a version of Semaphore that raises a ValueError in release() if it increases the internal counter above the initial value.
Language: python

Page: https://docs.python.org/3.10/library/asyncio-sync.html
Syntactic sugar: async with lock:
  foo
Implementation: await lock.acquire()
try:
  foo
finally:
  lock.release()
Language: python
Variables: lock: asyncio.Lock

Instruction: async.acquire()
Effect: Coroutine. Acquire the lock. if it is locked, wait until it gets unlocked
Language: python
Variables: lock: asyncio.Lock

Instruction: async.release()
Effect: release the lock.
Language: python
Variables: lock: asyncio.Lock
Example: RuntimeError if the lock is unlocked

Instruction: async.locked()
Language: python
Returns: Whether the lock is locked
Variables: lock: asyncio.Lock

Instruction: event.wait()
Effect: coroutine waiting until the event is set
Language: python
Variables: event: asyncio.Event

Instruction: event.set()
Effect: set the event
All tasks waiting for event to be set will be immediately awakened.
Language: python
Variables: event: asyncio.Event

Instruction: event.clear()
Effect: Clear (unset) the event
Tasks awaiting on wait() will now block until the set() method is called again.
Language: python
Variables: event: asyncio.Event

Instruction: event.is_set()
Language: python
Returns: whether the event is set
Variables: event: asyncio.Event

Instruction: condition.acquire()
Effect: Acquire the underlying lock.
This method waits until the underlying lock is unlocked, sets it to locked
Language: python
Variables: condition= asyncio.Condition(lock=None)

Instruction: condition.notify(n=1)
Effect: Wake up at most n tasks (1 by default) waiting on this condition. The method is no-op if no tasks are waiting.
Language: python
Variables: condition= asyncio.Condition(lock=None)
Exception: RuntimeError if condition is unlocked

Instruction: condition.locked()
Language: python
Returns: whether the underlying lock is acquired.
Variables: condition= asyncio.Condition(lock=None)

Instruction: condition.notify_all()
Effect: Wake up all tasks waiting on this condition.
Language: python
Variables: condition = asyncio.Condition(lock=None)
Extra: This method acts like notify(), but wakes up all waiting tasks.
Exception: RuntimeError if lock is not acquired

Instruction: condition.release()
Effect: Release the underlying lock.
Language: python
Variables: condition = asyncio.Condition(lock=None)
Exception: RuntimeError if lock is not acquired

Instruction: condition.wait()
Effect: Coroutine
This method releases the underlying lock, and then blocks until it is awakened by a notify() or notify_all() call. Once awakened, the Condition re-acquires its lock
Language: python
Variables: condition = asyncio.Condition(lock=None)
Exception: RuntimeError if lock is not acquired

Instruction: condition.wait_for(predicate)
Effect: wait until predicate() is truthy
Language: python
Returns: last value returned by predicate()
Variables: condition = asyncio.Condition(lock=None)
Exception: RuntimeError if lock is not acquired

Instruction: semaphore.acquire()
Effect: If the internal counter is greater than zero, decrement it by one. If it is zero, wait until a release() is called and return.
Language: python
Variables: semaphore = asyncio.Semaphore(value=1)

Instruction: semaphore.locked()
Language: python
Returns: Whether semaphore can not be acquired immediately.
Variables: semaphore = asyncio.Semaphore(value=1)

Instruction: semaphore.release()
Effect: Release a semaphore, incrementing the internal counter by one. Can wake up a task waiting to acquire the semaphore.
Language: python
Variables: semaphore = asyncio.Semaphore(value=1)