ptg10805159
Appendix C Chapter 12 Solutions 927
11.2 To change the thread ID of a pending job, the reader–writer lock must be held in
write mode to prevent anyone from searching the list while the ID is being
changed. The problem with the way the interfaces arecurrently defined is that
the ID of a job can change between the time that the job is found withjob_find
and the job is removed from the list by callingjob_remove.This problem can
be solved by embedding a reference count and a mutex inside thejobstructure
and havingjob_findincrement the reference count. The code that changes the
ID can then avoid any job in the list that has a nonzeroreference count.
11.3 First of all, the list is protected by a reader–writer lock, but the condition variable
needs a mutex to protect the condition. Second, the condition each thread
should wait to be satisfied is that there is a job for it to process, so we need to
create a per-thread data structure to represent this condition. Alternatively,we
can embed the mutex and condition variable in thequeuestructure, but this
means that all worker threads will wait on the same condition. If thereare many
worker threads, we can run into athundering herdproblem, whereby many
threads areawakened without work to do, resulting in a waste of CPU resources
and increased lock contention.
11.4 It depends on the circumstances. In general, both can be correct, but each
alternative has drawbacks. In the first sequence, the waiting threads will be
scheduled to run after we callpthread_cond_broadcast.Ifthe program is
running on a multiprocessor,some threads will run and immediately block
because we arestill holding the mutex (recall thatpthread_cond_waitreturns
with the mutex held). In the second sequence, a running thread can acquirethe
mutex between steps 3 and 4, invalidate the condition, and release the mutex.
Then, when we callpthread_cond_broadcast,the condition will no longer
be true, and the threads will run needlessly.This is why the awakened threads
must recheck the condition and not assume that it is true merely because
pthread_cond_waitreturned.
Chapter 12
12.1 This is not a multithreading problem, as one might first guess. The standardI/O
routines areindeed thread-safe. When we callfork,each process gets a copy of
the standardI/O data structures. When we run the program with standard
output attached to a terminal, the output is line buffered, so every time we print
aline, the standardI/O library writes it to our terminal. However, if we redirect
the standardoutput to a file, then the standardoutput is fully buffered. The
output is written when the buffer fills or the process closes the stream. When we
forkin this example, the buffer contains several printed lines not yet written, so
when the parent and the child finally flush their copies of the buffer,the initial
duplicate contents arewritten to the file.
12.3 Theoretically, if wearrange for all signals to be blocked when the signal handler
runs, we should be able to make a function async-signal safe. The problem is