Using Queues: Sleeping Instead of Spinning

This lesson discusses the use of queues to built more efficient locks.

The real problem with the previous approaches is that they leave too much to chance. The scheduler determines which thread runs next; if the scheduler makes a bad choice, a thread runs that must either spin waiting for the lock (our first approach) or yield the CPU immediately (our second approach). Either way, there is potential for waste and no prevention of starvation.

Thus, we must explicitly exert some control over which thread next gets to acquire the lock after the current holder releases it. To do this, we will need a little more OS support, as well as a queue to keep track of which threads are waiting to acquire the lock.

park() and unpark()

For simplicity, we will use the support provided by Solaris, in terms of two calls: park() to put a calling thread to sleep and unpark(threadID) to wake a particular thread as designated by threadID. These two routines can be used in tandem to build a lock that puts a caller to sleep if it tries to acquire a held lock and wakes it when the lock is free. Let’s look at the code excerpt below to understand one possible use of such primitives.

Get hands-on with 1200+ tech skills courses.