Synchronization Tools: Exercises
Synchronization Tools: Exercises
6
CHAPTER
Tools
Exercises
6.12 The pseudocode of Figure 6.15 illustrates the basic push() and pop()
operations of an array-based stack. Assuming that this algorithm could
be used in a concurrent environment, answer the following questions:
33
34 Chapter 6 Synchronization Tools
This has the effect of summing the elements in the array as a series
of partial sums, as shown in Figure 6.16. After the code has executed,
the sum of all elements in the array is stored in the last array location.
Are there any race conditions in the above code example? If so, identify
where they occur and illustrate with an example. If not, demonstrate
why this algorithm is free from race conditions.
6.15 The compare and swap() instruction can be used to design lock-free
data structures such as stacks, queues, and lists. The program example
shown in Figure 6.17 presents a possible solution to a lock-free stack
using CAS instructions, where the stack is represented as a linked list
of Node elements with top representing the top of the stack. Is this
implementation free from race conditions?
push(item) {
acquire();
if (top < SIZE) {
stack[top] = item;
top++;
}
else
ERROR
release();
}
pop() {
acquire();
if (!is empty()) {
top--;
item = stack[top];
release();
return item;
}
else
ERROR
release();
}
is empty() {
if (top == 0)
return true;
else
return false;
}
5 10 15 20 25 30 35 40
0 1 2 3 4 5 6 7
+ + + +
5 15 15 35 25 55 35 75
0 1 2 3 4 5 6 7
+ +
5 15 15 50 25 55 35 130
0 1 2 3 4 5 6 7
+
5 15 15 50 25 55 35 180
0 1 2 3 4 5 6 7
Figure 6.16 Summing an array as a series of partial sums for Exercise 6.14.
6.16 One approach for using compare and swap() for implementing a spin-
lock is as follows:
do {
old node = top;
new node->next = old node;
}
while (compare and swap(top,old node,new node) != old node);
}
value t pop() {
Node *old node;
Node *new node;
do {
old node = top;
if (old node == NULL)
return NULL;
new node = old node->next;
}
while (compare and swap(top,old node,new node) != old node);
while (true) {
flag[i] = true;
while (flag[j]) {
if (turn == j) {
flag[i] = false;
while (turn == j)
; /* do nothing */
flag[i] = true;
}
}
/* critical section */
turn = j;
flag[i] = false;
/* remainder section */
}
if (getValue(&sem) > 0)
wait(&sem);
Many developers argue against such a function and discourage its use.
Describe a potential problem that could occur when using the function
getValue() in this scenario.
6.18 The first known correct software solution to the critical-section problem
for two processes was developed by Dekker. The two processes, P0 and
P1 , share the following variables:
while (true) {
while (true) {
flag[i] = want in;
j = turn;
while (j != i) {
if (flag[j] != idle) {
j = turn;
else
j = (j + 1) % n;
}
flag[i] = in cs;
j = 0;
/* critical section */
j = (turn + 1) % n;
turn = j;
flag[i] = idle;
/* remainder section */
}
All the elements of flag are initially idle. The initial value of turn is
immaterial (between 0 and n-1). The structure of process Pi is shown in
Figure 6.19. Prove that the algorithm satisfies all three requirements for
the critical-section problem.
Exercises 39
typedef struct {
int available;
} lock;
int hits;
mutex lock hit lock;
hit lock.acquire();
40 Chapter 6 Synchronization Tools
hits++;
hit lock.release();
atomic t hits;
atomic inc(&hits);