Information Technology Reference
In-Depth Information
signal()
or all (if
broadcast()
of the TCBs on that condition variable's wait-
ing queue are moved to the scheduler's ready list. This changes those threads
from theWaitingstate to theReadystate. At some later time, the scheduler
selects aReadythread and runs it by moving it to theRunningstate.
Locks are similar.
Lock::acquire()
on a busy lock puts caller into the
Waitingstate, with the caller's TCB on a list of waiting TCBs associated with
the lock. Sometime later, when the lock owner calls
Lock::release()
, the TCB
is moved to the ready list and the thread transitions to theReadystate.
Notice that threads that areRunningorReadyhave their state located at a
pre-dened, \global" location like the CPU (for aRunningthread) or the sched-
uler's list of ready threads (for aReadythread). However, threads that are
Waitingtypically have their state located on some per-lock or per-condition-
variable queue of waiting threads. Then, a
Cond::signal()
,
Cond::broadcast()
,
or
Lock::release()
call can easily find and reenable a waiting thread for that
particular condition variable or lock.
5.4.3
Example: Blocking bounded queue
As an example, consider the bounded queue described in Section 5.3.2. Suppose
we change the interface so that
insert()
blocks until there is room to insert an
item and
remove()
blocks until there is an item to remove.
BBQ.h
in Figure 5.9
denes the blocking bounded queue's interface and public methods.
BBQ.cc
in
Figure 5.10 denes the queue's implementation.
Notice that as in
TSQueue
, we acquire and release the lock at the beginning
and end of the public methods (e.g.,
insert()
and
remove()
). Now, however,
we can (atomically) release the lock and wait if there is no room in
insert()
or
there is no item in
remove()
. Before returning,
insert()
signals on
itemAdded
since a thread waiting in
remove()
may now be able to proceed; similarly,
remove()
signals on
itemRemoved
before it returns.
We
signal()
rather than
broadcast()
because each
insert()
allows at
most one
remove()
to proceed and vice versa.