Lecture 5 - Synchronization Flashcards

1
Q

What is the difference between competing and cooperating concurrent processes?
What are each type’s properties?
How does the OS deal with each?

A

Competing
• Processes that do not work together cannot affect the execution of each other, but they can compete for devices and other resources
Properties: Deterministic; reproducible
* can stop and restart without side effects
* can proceed at arbitrary rate
->OS carefully allocates resources and isolates processes from each other

Cooperating
• Processes that are aware of each other, and directly (by exchanging messages) or indirectly (by sharing a common object) work together, may affect the execution of each other
Properties: Non-deterministic; May be irreproducible
* Share a common object or exchange messages
* Subject to race conditions –coming up
OS provides mechanisms to share resources

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What’s the main problem with competing processes?

A

Some processes can starve

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Why would we want Cooperating processes?

A
  • Sharing resources (like a global task queue)
  • Dividing a job into pieces and executing concurrently to run faster
  • Solve problems modularly (like piping)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What problems can occur with interleaving cooperating threads?

A

Race conditions: Variables could be changed by the other threads.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

How do you avoid Race Conditions?

A

Prohibit more than one thread from reading and writing shared data at the same time through:
Mutual exclusion: When one process is reading or writing a shared data, other processes should be prevented from doing the same

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is a Critical Section in a process?

A

Part of the processes that accesses shared data.
If we arrange the processes runs such that no two programs are in their critical sections at the same time, race conditions can be avoided.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

(EXAM QUESTION) What are the 4 conditions for multiple programs to cooperate correctly and efficiently?

A
  • No two processes may be simultaneously in their critical sections
  • No assumptions be made about speeds or number of CPUs
  • No process running outside its critical section may block other processes
  • No process should have to wait forever to enter its critical section
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

(EXAM QUESTION) What are 3 requirements for critical sections?

A
  • Critical region execution should be atomic i.e., its runs “all or none”
  • Should not be interrupted in the middle
  • For efficiency, we need to minimize the length of the critical sections

Most inefficient scenario: Whole program is a critical section – no multi-programming!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Why would disabling all interrupts work as a solution to concurrency in critical sections?
Why is it not a good idea?

A

Works:
• Because interrupts cause out-of-order execution due to interrupt servicing
• With interrupts disabled, a process will run until it yields the resource voluntarily

Not a good idea:
• Because OS won’t allow a user process to disable all interrupts – OS operation will be hindered too!
• Does not work on multiprocessors

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What’s the problem with Strict Alternation?

A

Because one process couldn’t get into the critical section over and over unless the other process does so as well. If the other process isn’t interested in entering critical section, the first process starves.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What’s busy waiting? When should it be used?

What’s a spin lock?

A

When you’re continuously waiting for another variable, which sucks up the CPU time. Should be used when the expected wait is short.

A spin lock is a lock that uses busy waiting

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Kernel level multi-threads are used for concurrent processing in a data-parallel application. The application has a critical section. If a single thread of execution is used the critical section takes 2 seconds and other parts take 6 seconds. We have a large dataset so we use 2 threads. What is the run time? We have an even larger dataset so we use 8 threads. What is the run time? Assume single CPU and ideal time sharing (no overhead). All threads starting at the same time.

A

2 threads: 18 seconds

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Why does this mutual exclusion solution not work?

/* process 0 */
while (turn != 0);
/* critical section */
turn = 1;
/*  process 1 */
while (turn != 1);
/* critical section */
turn = 0;
A

A Single key shared by the two processes

Each have their own key to the critical section, so they only grant access to themselves!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What’s a livelock?

A

Pretty much like a deadlock, but useless programs running instead of blocking (in mutual exclusion yielding)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Write Peterson’s Algorithm:

Why does it work?

A
/* process 0 */
flag[0] = true;
turn = 1;
while (flag[1] &&turn == 1);
/ * critical section */
flag[0] = false;
/* remainder */
/* process 1 */
flag[1] = true;
turn = 0;
while (flag[0] &&turn == 0);
/* critical section */
flag[1] = false;
/* remainder */

It works because both while locks are exclusive because of the turn variable. No deadlock and live-lock can’t occur.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What are two benefits hardware synchronization can provide?

A
  • > make the solution more efficient

- > make it scalable to more processes?

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

What does the CPU instruction:
TSL RX, LOCK
do?

A

Read the contents of memory location LOCK into register RX and stores a non-zero value at memory location LOCK.
This makes operation of reading and writing indivisible -atomic.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What are the advantages of Machine Instruction Mutual Exclusion?

A
  • applicable to any number of processes
  • can be used with single processor or multiple processors that share a single memory
  • simple and easy to verify
  • can be used to support multiple critical sections, i.e., define a separate variable for each critical section
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

What are the disadvantages of Machine Instruction Mutual Exclusion?

A
  • Busy waiting is employed–process waiting to get into a critical section consumes CPU time
  • Starvation is possible–selection of entering process is arbitrary when multiple processes are contending to enter
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

How do semaphores work?

A
  • two or more processes can cooperate by sending simple messages
  • a process can be forced to stop at a specific place until it receives a specific message
  • complex coordination can be satisfied by appropriately structuring these messages
  • for messaging a special variable called semaphore s is used
  • to transmit a message via a semaphore a process executes signal(s)
  • to receive a message via a semaphore a process executes wait(s)
21
Q

What are two types of semaphores?

What’s the difference between them?

A

Binary: semaphore with 0 or 1 value (or true for false)
Counting: initial value ranging from 0 to large, for multiple critical resources (called general semaphores)

22
Q

What are Monitors?

Write the pseudo code for monitors.

A
■A high-level abstraction that provides a convenient and effective mechanism for process synchronization
■Abstract data type, internal variables only accessible by code within the procedure
■Only one process may be active within the monitor at a time
Pseudo-code:
Monitor monitor-name{
// shared variable declarations
function P1 (...) { .... }
function P2 (...) { .... }
function Pn (...) {......}
initialization code (...) { ... }
}
23
Q

What’s the difference between semaphores and conditional values?

A

When you do a signal on semaphore, you have to be careful because because semaphores have memories. Conditional variables don’t, its just a mechanism to wait.

24
Q

In the philosopher problem, why don’t we put the eat() in the monitor?

A

Because it doesn’t need protected. Putting it in the monitor blocks other people from using the monitor unnecessarily.

25
Q

What’s the problem with the monitor approach to the philosopher problem?

A

Starvation can occur even if deadlocks can’t.

26
Q

Define Race Conditions

A

When two or more processes are reading or writing some shared data and final result depends on who runs precisely when is a race condition.

27
Q
IDENTIFY THE CRITICAL SECTION
authenticate user
open account
load R1, balance
load R2, amount (-ve for withdrawal)
add R1, R2
store R1, balance
close account
display account inf
A

load R1, balance
load R2, amount (-ve for withdrawal)
add R1, R2
store R1, balance

28
Q

Why is using a lock variable in this way not gonna work?:
If lock== 0 set lock=1 and enter_region
If lock== 1 wait until lock becomes 0

A

Because lock is also subject to race conditions. both processes can get to lock = 1 if lock == 0, before lock = 1 is reached in either (context-switching).

29
Q
1. Why would this not work for mutual exlusion?
/ * process 0 */
while (flag[1]);
flag[0] = true;
/* critical section */
flag[0] = false;
/ * process 1 */
while (flag[0]);
flag[1] = true;
/* critical section */
flag[1] = false;
  1. How could this be solved by reordering the lines?
    What’s the problem with this solution?
  2. How could we solve the latter solution?
    Whats the problem with this solution?
A
  1. A context switch to process 1 after the while loop and before the flag[0] in process 0 gets set could fuck up the mutual exclusion, and both critical sections would pass the while loop and go into critical sections.
2. The mutual exclusion could be solved by setting the flag to true before the while loop.
flag[0] = true;
while (flag[1]);
/* critical section */
flag[0] = false;

A deadlock could occur if a context switch to process 1 happens right after the flag[0] is set to true. (both flag would be set to true)

3. We could solve this by implementing yielding behavior:
/* process 0 */
flag[0] = true;
while (flag[1])
   {
   flag[0] = false;
    /* random delay */
    flag[0] = true;
    }
/* critical section */
flag[0] = false;

The problem with this solution is livelock, if both the random delays are synchronized.

30
Q

Implement hardware synchronization (mutual exclusion) with TSL RX, LOCK.

A

enter_section:
TSL RX, LOCK // copy LOCK into RX, set lock to >0
CMP RX, #0 // tst if LOCK was 0
JNE enter_section // if lock was not 0, retry
RET

leave_region:
MOVE LOCK, #0
RET

31
Q

Define the priority inversion problem

A

Suppose a computer runs two processes H: high priority and L: low priority

  • > scheduler always runs H when it is in ready state
  • > at a certain time L is in its critical section and H become runnable
  • > H begins busy waiting to enter the critical section
  • > L is never scheduled to leave the critical section there is a deadlock
32
Q

What’s the Sleep/Wakeup Approach to mutual exclusion?

What’s the key element to implement these?

A
  • > Sending signals between processes signaling each other when they’re in/out of critical sections, so that no busy waiting occurs.
  • > Implemented by the Semaphores.
33
Q

2 Semaphore elements

3 Semaphore operations

A

Elements

  1. Count - Number of concurrent processes running
  2. Process Queue

Operations

  1. can be initialized to a nonnegative value –set semaphore
  2. wait –decrements the semaphore value –if value becomes negative, process executing wait is blocked and put into queue
  3. signal –increments the semaphore value –if value is not positive, a process blocked by a wait operation is unblocked and taken from queue
34
Q

What does it mean for Wait and Signal primitives in Semaphores to be atomic?

A

They cannot be interrupted and treated as an indivisible step

35
Q

What’s the difference between strong and weak semaphore?

A

Strong: Process queue is FIFO
Weak: No process ordering

36
Q

What are three problems to worry about with Semaphore Queues?

A

Queue Overflow: Too many processes pushed to queue from Producer
Queue Insertion: What’s the ordering? FIFO/none?
Queue Underflow: Not enough processes pushed to queue so Consumer sleeps

37
Q

Do Monitors use semaphores or condition variables?

What operations are available on these?

A

Monitors use condition variables to provide user-tailored synchronization and manage each with a separate queue for each condition.

Two operations are allowed on a condition variable:
●x.wait() –a process that invokes the operation is suspended until x.signal()
●x.signal() –resumes one of processes (if any) that invoked x.wait()
-> If no x.wait() on the variable, then it has no effect on the variable

38
Q

How many processes can be active in a Monitor at once?

A

Only one process can be active in the monitor at once. Some will be waiting to get in, others will be waiting on conditions in the monitor

39
Q

If process P invokes x.signal(), and process Q is suspended in x.wait(), what should happen next?
(HINT) Both Q and P cannot execute in parallel. If Q is resumed, then P must wait.

Name three options

A
  1. Signal and wait –P waits until Q either leaves the monitor or it waits for another condition (HOARE’S)
  2. Signal and continue –Q waits until P either leaves the monitor or it waits for another condition (HANSEN’S)
  3. P signals and leaves the monitor immediately
40
Q

What are 3 classical synchronization problems?

A

Bounded-Buffer Problem
Readers and Writers Problem
Dining-Philosophers Problem

41
Q

Define the Bounder-Buffer Problem.

Write the pseudo-code for both Producer and Consumer.

A

n buffers, each can hold one item
Semaphore mutex initialized to the value 1
Semaphore full initialized to the value 0
Semaphore empty initialized to the value n

PRODUCER
while (true) {
     /* produce an item in next_produced */
     wait(empty); wait(mutex); 
     /* add next produced to the buffer */
     signal(mutex); 
     signal(full); 
}
CONSUMER
while (true) { 
     wait(full); 
     wait(mutex); 
     /* remove an item from buffer to next_consumed */  
     signal(mutex); 
     signal(empty);
     /* consume the item in next consumed */
}
42
Q

Define the Readers-Writers Problem.

Write the pseudo code for Readers and Writers.

A

A data set is shared among a number of concurrent processes
Readers – only read the data set; they do notperform any updates
Writers – can both read and write

Problem – allow multiple readers to read at the same time
Only one single writer can access the shared data at the same time
Several variations of how readers and writers are considered – all involve some form of priorities
Shared Data
Data set
Semaphore rw_mutex initialized to 1
Semaphore mutex initialized to 1
Integer read_count initialized to 0

WRITER
while (true) {
      wait(rw_mutex); ... 
      /* writing is performed */ ... 
      signal(rw_mutex); 
}
READER
while (true){
     wait(mutex);
     read_count++;
     if (read_count == 1) 
          wait(rw_mutex); 
     signal(mutex); 
 /* reading is performed */ 
     wait(mutex);
     read count--;
     if (read_count == 0) 
          signal(rw_mutex); 
     signal(mutex); 
}
43
Q

Define the Dining-Philosophers Problem

A

■Philosophers spend their lives alternating thinking and eating
■Don’t interact with their neighbors, occasionally try to pick up 2 chopsticks (one at a time) to eat from bowl
●Need both to eat, then release both when done
■In the case of 5 philosophers
●Shared data:
-»Bowl of rice (data set)
-»Semaphore chopstick [5] initialized to 1

44
Q

what’s the problem with this Semaphore solution to the dining philosophers problem?

while (true){ 
     wait (chopstick[i] );
     wait (chopStick[ (i + 1) % 5] );
     /* eat for awhile */
     signal (chopstick[i] );
     signal (chopstick[ (i + 1) % 5] );
     /* think for awhile */
}

Give two solutions to fix this.

A

A deadlock can occur on the second wait if all the philosophers grab their chopstick first.

  1. Grab both forks at the same time.
  2. Mix the order which philosophers grab their forks
45
Q

Write a Monitor solution pseudo-code to the Dining philosophers problem.

What’s the problem with this solution?

A
Monitor DiningPhilosophers{ 
enum { THINKING; HUNGRY, EATING) state [5] ;
condition self [5];
void pickup (int i) { 
state[i] = HUNGRY;
test(i);
if (state[i] != EATING) self[i].wait;
}
void putdown (int i) 
{ state[i] = THINKING;
// test left and right neighbors
test((i + 4) % 5);
test((i + 1) % 5);
}
void test (int i) { 
if ((state[(i + 4) % 5] != EATING) &&(state[i] == HUNGRY) &&(state[(i + 1) % 5] != EATING) ) { 
state[i] = EATING ;
self[i].signal () ;
}
}
initialization_code() { 
for (int i = 0; i < 5; i++)state[i] = THINKING;
}
}

No deadlock, but starvation is possible

46
Q

Implement a Semaphore using a Monitor.

A
Monitor Sem {
 int count;
condvar block;
swait(){
     count--;
     if(count<0) block.wait()
}
ssignal() {
     count ++;
     if (count<=o)
     block.signal()
}

init(c) {
count = c;
}
}

47
Q
  1. Implement a Producer Consumer solution using a Monitor, with the buffer inside.
  2. Which Wait and Signal method is implemented here? Hoarse’s or Hansen’s?
  3. What’s the problem with this solution? How could you solve this?
  4. Why do we not want the buffer to be inside the monitor?
A
Monitor Prod_consumer{
int count = 0;
condvar nospace;
condvar noitems;
int inptr, outptr = 0;
buffer_t *buffer [SLOTS];
buffer_t *ptr;
void produce(buffer_t * item) {
     count ++;
     if (count > slots) nospace.wait()
     inptr = (inptr++) % SLOTS;
     memcpy(buffer[inptr],  item);
     noitems.signal();
}
buffer_t * consume() {
     if (count==0) noitems.wait()
     count --;
     outptr = (outptr+) % SLOTS;
     ptr = buffer[outptr];
     nospace.signal();
     return ptr;
}
  1. HOARE’S: signal and wait
  2. The problem is that the consumer only returns a pointer, so the producer can override it on the next run because it is a circular buffer. We could solve it by doing a memcopy(ptr, buffer[outptr]).
  3. We don’t want to put large items in monitors.
48
Q
  1. Implement a Producer Consumer solution using a Monitor, with the buffer outside.
  2. What’s a minor problem with this solution?
A
Monitor Prod_consumer{
int count = 0;
condvar nospace;
condvar nospace;
int inptr, outptr = 0;
buffer_t *ptr;
int produce_lock() {
     count ++;
     if (count > slots) nospace.wait()
     return inptr = (inptr++) % SLOTS;
}
int consume_lock(){
     if (count==0) noitems.wait()
     count --;
     return outptr = (outptr+) % SLOTS;
}
int produce_unlock(){
     noitems.signal();
}
int consume_unlock(){
     nospace.signal();
}
}
  1. We still run into a circular buffer problem where the producer can override the consumer. We can solve this by simply adding an extra buffer slot?.
49
Q
  1. Implement a Monitor using a Semaphore.

2. What happens if you signal a condition variable while no one is waiting? How is this different than a semaphore?

A

semaphore mutex = 1;
semaphore next = 0;
int next_count = 0;

Each function in F will be replaced by

wait(mutex);
// body of F
if (next_count > 0)
    signal(next);
else 
    signal(mutex);

For each condition variable x, we have:

Semaphore x_sem; // (initially = 0)
int x_count = 0;

The operation x.wait() can be implemented as:

x_count++;
if (next_count >0)
     signal(next);
else
     signal(mutex);
wait(x_sem);
x_count--;
The operation x.signal() can be implemented as:
if (x_count > 0) {
next_count++;
signal(x_sem);
wait(next);
next_count--;
}

Nothing. A semaphore increases the inner count, so we have to be careful.