You are on page 1of 13

Concurrency Mechanisms: Lamport’s Bakery Algorithm

A paper submitted to Polytechinc Institute of New York University for the


Operating Systems – I Masters Course

2008

Submitted by: Anshul Jain


Research Advisor: Prof Daniel Katz

1
List of Contents

Abstract ..........................................................................................................................3

Introduction.....................................................................................................................4

Mutual Exclusion.............................................................................................................4

IPC and issues therein......................................................................................................5

Concurrency and issues therein.......................................................................................5

Analogy...........................................................................................................................7

Implementation of the algorithm.....................................................................................7

The Algorithm.................................................................................................................9

Drawbacks of various algorithms..................................................................................10

Issues and Future Studies..............................................................................................11

References ....................................................................................................................13

2
Abstract:
The mutual exclusion problem:
(also called as the concurrent programming problem)

The problem is to ensure that no two processes are in their critical section at the same
time.

Several solutions have been implemented namely Knuth [1], deBruijn [2], Eisenberg and
McGuire [3] to Dijkstra's [4] concurrent programming problem. But none of these
solutions work in a distributed multiple processor environment. These solutions and those
by Dekker’s, Peterson’s and semaphores assume that there is some form arbitration when
accessing a word from the memory or they rely on specialized atomic instructions. This
drawback makes them unsuitable for use in a true multicomputer system (rather than a
timeshared multiprocessor system) with shared memory: the failure of a single unit will
halt the entire system.
Lamport’s bakery algorithm [5] provides a solution which enables the multi-computer
system (a.k.a distributed systems) to function despite the failure of individual
components and its forte lies in the fact that it does not assume that lower level mutual
exclusion by the memory system.

This paper outlines the different hardware and software solutions for mutual exclusion
(which in turn provides concurrency) and goes into detail on the Lamport’s Bakery
Algorithm.

Key Words and Phrases: critical section, mutual exclusion, mutex, concurrent programming,
multiprocessing, semaphores
Note: The fundamental difference between threads and processes is that processes have separate address
spaces, whereas threads share address spaces. For this paper we ignore this distinction, using the two terms
interchangeably.

3
Introduction:
Perhaps the most central aspect of operating system design is the management of
processes and threads, which is of utmost importance in today’s indispensable
multiprocessing environment.
It is common for multiple threads to simultaneously access the same resources. Data
corruption can occur if two or more threads try to write into the same memory location,
or if one thread reads a memory location before another has finished writing into it.
Lamport's bakery algorithm is one of many mutual exclusion algorithms designed to
prevent threads entering critical sections of code concurrently.

Mutual Exclusion:
Any time there are multiple threads of program logic that access the same data, and
execute at the same time, problems arise. The portions of code that access these shared
data structures are known as critical sections, and the practice of letting only one run at a
time is known as mutual exclusion. [6]

Fig: Representation of threads using mutual exclusion [7]

4
IPC and issues therein:
In an operating system with multiple processes, processes inevitably and frequently need
to communicate with each other. Earlier this was done using interrupts, but in a modern
operating system this inter process communication (IPC) should be achieved in a better,
more structured way.
There are three issues to IPC:
• How can one process pass information to another?
• Providing Mutual Exclusion when the processes/threads (therein) are in
contention for a single resource resulting in a race condition. It may be something
evident as two programs using a printer at the same time, or something that’s a
little less visible (and hence more troublesome) like two threads updating a global
variable in an order that wasn’t intended.
• Proper sequencing when dependencies are present: the classic producer/consumer
problem.

Concurrency and issues therein:


And then we have concurrency to achieve, Concurrent use of shared resources is a source
of many difficulties.
Total ordering of events:

Fig: total ordering of events [8]

5
Issues in concurrency:
• Deadlock
• Livelock
• Fairness
• Starvation
• Race Conditions

We use several hardware and software techniques to avoid and resolve the above
mentioned issues in IPC and concurrency.
• Hardware solutions:
o Disable Interrupts
o Atomic instructions – TestAndSet( ) and Swap( )
• Software solutions:
o Dekker's algorithm
o Peterson's algorithm
o Lamport's bakery algorithm
o Semaphores
o Monitors
o Message passing

6
Analogy:
The Bakery Algorithm
Lamport's bakery algorithm works for multiple competing threads of control when the
only communication between them is shared memory (in other words, no special
mechanisms such as semaphores, atomic set-and-test, and so forth are required) eg in a
multicomputer distributed system.

The metaphor for this algorithm is a bakery that requires customers to take a number and
wait till their number is called.
Lamport envisioned a bakery, as customers enter the bakery they are given a number and
asked to stand in a waiting area till their number is called. The baker calls out the number
that will be served next and the customer with that number gets serviced. All other
customers must wait in a queue until the baker finishes serving the current customer and
the next number is displayed. When done the customer loses their number and can then
do whatever they want.

In the computer world, the 'customers' will be threads, and the baker will be the critical
section of code that can be used according to the principles of mutual exclusion.

Implementation of the algorithm:


What is significant about the bakery algorithm is that it implements mutual exclusion
without relying on any lower-level mutual exclusion.
A mutual exclusion algorithm that assumes atomics reads and writes is assuming lower-
level mutual exclusion. Such an algorithm cannot really be said to solve the mutual
exclusion problem.
-Leslie Lamport

7
Pseudocode [9]:

// logic used by each thread...


// where "(a, b) < (c, d)" means "(a < c) or ((a == c) and (b < d))"
// declaration and initial values of global variables
Choosing: array [1..N] of bool = {false};
Number: array [1..N] of integer = {0};

1 lock(integer i) {
2 Choosing[i] = true;
3 Number[i] = 1 + max(Number[1], ..., Number[N]);
4 Choosing[i] = false;
5 for (j = 1; j <= N; j++) {
6 // Wait until thread j receives its number:
7 while (Choosing[j]) { /* nothing */ }
8 // Wait until all threads with smaller numbers or with the
9 //same number, but with higher priority, finish their work:
10 while((Number[j]!= 0) && ((Number[j], j)<(Number[i], i))) {
11 /* nothing */
12 }
13 }
14 }
15
16 unlock(integer i) {
17 Number[i] = 0;
18 }
19
20 Thread(integer i) {
21 while (true) {
22 lock(i);
23 // The critical section goes here...
24 unlock(i);
25 // non-critical section...
26 }
27 }

8
The Algorithm:
This is a non-token-based algorithm with no central controller.
For each process, i, there are two values, Choosing [i] and Number[i], giving the status of
process I and the number it has picked.

Number[i] = 0 //Process i is not in the bakery.


Number[i] > 0 // Process i has picked a number and is in the bakery.

Choosing[i] = True // Process i is trying to pick a number.


Choosing[i] = False // Process i is not trying to pick a number.

When Number[i] = min( for all j, N[j] where N[j] > 0 ) // Process i
is allowed into the critical section.

When trying to pick a number the thread raises it’s choosing flag which is true till it has
finished picking a number. This is analogous to a person raising his hand (line 2) when he
wants a number for his order. He looks around the bakery to see if any hands are up and
if none are he raises his own hand and picks the next available number (line 3). Once he
is done choosing his number he puts his hands down and waits for his turn to be
processed (line 4).

Note: Lamport’s algorithm allows two incoming processes to pick the same number, in
such a case these processes are made aware of the tie and the process with the higher
priority gets to execute its critical section first.

Next the process waits till all the processes which have numbers smaller than its own
finish their work (line 7 and 10).

In its distributed implementation this algorithm can be produced directly by storing


Number[i] and Choosing[i] locally with the process.

This means that mutual exclusion can be done without any central authority!

9
Each process must read the variables of all other processes a minimum of 3 times -- once
to select a ticket number, once to see if anyone else is in the process of selecting a
number, and once to see if it holds the minimum ticket.

To return its ticket, and exit the critical section, the process sets its own ticket to zero
(line 17):
Number[i] = 0;

Drawbacks of various algorithms:


We now list assorted drawbacks and shortcomings of [1-4] and see how lamport’s bakery
algorithm [5] overcomes them for it to be used effectively in a distributed multicomputer
system or in a SMP for that matter:

Disable Interrupts:
Drawback:
Not feasible in multiprocessor systems for obvious reasons.

Atomic instructions – TestAndSet( ) and Swap( )


Drawback:
Implementing atomic instructions on multiprocessors is not a trivial task and it’s
especially hard for the hardware designers.

Dekker’s and Peterson’s algorithm:


Drawback:
Many modern CPUs execute their instructions in an out-of-order fashion. This algorithm
won't work on SMP machines equipped with these CPUs without the use of memory
barriers.

10
Semaphores:
Drawback:
The simplest implementation of semaphores results in busy waiting. This can be worked
around by embedding the logic of the thread blocking itself (going in a suspend state)
instead of running in a loop.

Mutexes:
Are like binary semaphores, but add the concept of ownership; that is, only the process
who took the mutex can give it back. [10]
Drawback:
Mutexes are very easy to use, but can drastically slow down threaded code when
overused. But if multiple reader threads run at the same time, they end up spending a
large percentage of their total running time waiting for the mutex to become available.

Issues and Future Studies:

Issue 1:
There are issues in implementing the pseudocode using some languages because of the
absence of constructs that provide atomic instructions and data structures for thread
management, eg javascript is a popular language that’s used in web applications but it
does not provide any mutual exclusion mechanisms neither there is any thread API. There
is no way to yield the CPU to other threads and no way to create a new thread to manage
other threads.

Issue 2:
Also it difficult to represent the pair: "(a, b) < (c, d)" atomically in many languages

One possible solution:


We need to make the compilers aware of this and provide language constructs.

11
Issue 3:
Pushing the frequency of the processor alone would not suffice the power hungry
applications of today, we have come to realize that parallelism is the roadmap to take.
There are some more areas where Lamport’s Algorithm will fail, in using the massively
parallel architecture for computations as in a GPU (graphics Processing Unit).

A example is NVIDIA-CUDA (Compute Unified Device Architecture) which enables


some applications to harness the extraordinary computational power of the gpu (GPUs
have a parallel "many-core" architecture, each core capable of running thousands of
threads simultaneously).
CUDA has also been used to accelerate applications in computational-biology and
cryptography to name a few.
Unfortunately traditional concurrency algorithms cannot be used to maintain concurrency
amongst the thousands of threads that are running on the gpu at any given instant.

12
References:

[1.] Knuth, D.E. Additional comments on a problem in concurrent programming control.


Comm. Acre 9, 5 (May 1966), 321-322.

[2.] deBruijn, N.G. Additional comments on a problem in concurrent programming


control Comm. ACM 10, 3 (Mar. 1967), 137-138.

[3.] Eisenberg, M.A., and McGuire, M.R. Further comments on Dijkstra's concurrent
programming control problem. Comm. ACM 15, 11 (Nov. 1972), 999.

[4.] Dijkstra, E.W. Solution of a problem in concurrent programming control. Comm.


ACM 8, 9 (Sept. 1965), 569.

[5] Lamport, L. A new solution of Dijkstra's concurrent programming problem. Commun.


ACM 17, 8 (Aug. 1974), 453-455.

[6] [http://dev.aol.com/ajax-mutual-exclusion]

[7] [http://www.ibm.com/developerworks/library/l-posix2]

[8] [http://www.gup.unilinz.ac.at/thesis/diploma/christian_schaubschlaeger/html/
chapter03a9.html ]

[9] [http://en.wikipedia.org/wiki/Lamport's_bakery_algorithm]

[10] [http://www.isd.mel.nist.gov/projects/rtlinux/rtutorial-2.0/doc/mutex.htm]

13