Low-level thread locking primitive
A Lock is a low-level constructor for ensuring that only one thread works with a certain object at a given time, or runs a piece of code (called the critical section).
my = 0;my = Lock.new;await (^10).map:say ; # OUTPUT: «10␤»
Locks are re-entrant, that is, a thread that holds the lock can lock it again without blocking.
method protect(Lock: )
&code and makes sure it is only run in one thread at once.
Note that the Lock itself needs to be created outside the portion of the code that gets threaded and it needs to protect. In the first example below, Lock is first created and assigned to
$lock, which is then used inside the Promises to protect the sensitive code. In the second example, a mistake is made, the
Lock is created right inside the Promise, so the code ends up with a bunch of separate locks, created in a bunch of threads, and thus they don't actually protect the code we want to protect.
# Right: $lock is instantiated outside the portion of the# code that will get threaded and be in need of protectionmy = Lock.new;await ^20 .map:# !!! WRONG !!! Lock is created inside threaded area!await ^20 .map:
Acquires the lock. If it is currently not available, waits for it.
my = Lock.new;.lock;
Releases the lock.
my = Lock.new;.lock;.unlock;
mymethod condition(Lock: --> ConditionVariable)
Returns a condition variable. Compare https://web.stanford.edu/~ouster/cgi-bin/cs140-spring14/lecture.php?topic=locks or https://en.wikipedia.org/wiki/Monitor_%28synchronization%29 for background.
my = Lock.new;.condition;