Professional Documents
Culture Documents
1
Cooperating Processes
• Multiprogramming created an environment for
concurrent processes to execute
• Concurrent processes executing in the operating system
allows for the processes to cooperate with other
processes.
• Processes are cooperating if they can affect each other.
• The simplest example of how this can happen is where
two processes are using the same file. One process may
be writing to a file, while another process is reading from
the file; so, what is being read may be affected by what is
being written.
• Cooperation & Sharing is important for several reasons:
– Information sharing, computation speedup, modularity,
convenience
• cooperating processes are processes that
cooperate to achieve a specific task.
• A task is initially broken into subtasks , each
subtask is assigned to a process that should pass
the result (or input) to another process and so on,
until the task is done.
• Multiple cooperating processes introduce the
potential for new synchronization problems in
software implementation called Critical section
Synchronization problems
• These synchronization problems can occur
whenever two or more concurrent
processes use any shared resource.
• How these synchronization problems arise
in concurrent applications?
• Abstract mechanism that can be used to
solve synchronization problems.
Critical sections
• A real life example
– In automobile transportation, intersections are
part of a street, but they are unique part of the
street because the intersection is a shared
between two different streets.
– The traffic intersection is a critical section of
these two streets, in the sense that only one
vehicle can be in the intersection at a time.
– Eithor vehicle can use the critical section,
provided that the others is not using it
Traffic Intersections
Critical section
Critical sections
• Critical sections occur in concurrent software
whenever two processes access a common
shared variable
balance+=amount balance-=amount
balance
Compiled instructions
code schema for p1 code schema for p2
14
Boolean Flag
15
A Semaphore
Dijkstra Semaphore
• Semaphore is an OS abstract type that
performs operations similar to the traffic
light.
• Invented in the 1960s
• Conceptual OS mechanism, with no specific
implementation defined
• Basis of all contemporary OS
synchronization mechanisms
Semaphore
• Semaphore is a non negative integer
variable whose values can be changed only
by one of the two indivisible access routines
P() & V()
• P () : Proberen - to test
semaphore mutex = 1;
fork(proc_0, 0);
fork(proc_1, 0);
Shared Account Balance Problem
Proc_0() { proc_1() {
. . . . . .
/* Enter the CS */ /* Enter the CS */
P(mutex); P(mutex);
balance += amount; balance -= amount;
V(mutex); V(mutex);
. . . . . .
} }
semaphore mutex = 1;
fork(proc_0, 0);
fork(proc_1, 0);
Types of Semaphore
• Binary Semaphore
– They can takes only 2 values - 0 &1
• Counting Semaphore
– counting semaphores take more than two
values, they can have any value you want. The
max value X they take allows X process/threads
to access the shared resource simultaneously.
Mutex
• Simplest and most efficient thread synchronization
mechanism
• Like a semaphore with maximal value 1
• A special variable that can be either in
– locked state: a distinguished thread that holds or
owns the mutex; or
– unlocked state: no thread holds the mutex
• When several threads compete for a mutex, one wins.
The rest block at that call
Classical Synchronization Problems
Writers
Readers
Readers-Writers Problem (2)
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader
Reader
Shared Resource
Readers-Writers Problem (3)
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Shared Resource
Readers-Writers Problem (4)
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader Writer
Writer
Reader
Reader
Reader
Reader
Writer
Writer
Shared Resource
First Solution
• As long as the reader holds the resource and
there are new readers arriving, any writer
must wait for the resource become available.
– The first reader accessing the shared resource
must compete with any writers, but once a reader
succeeds, other readers can pass directly into the
critical section, provided that at least one reader is
in the critical section
– Readers keep the count of the no. of readers in
the critical section, with the readcount variable
which is updated and tested inside its own critical
section
reader() {
First Solution writer() {
while(TRUE) { while(TRUE) {
<other computing>; <other computing>;
P(mutex); P(writeBlock);
readCount++; /* Critical section */
if(readCount == 1) access(resource);
P(writeBlock); V(writeBlock);
V(mutex); }
/* Critical section */ }
access(resource);
P(mutex);
readCount--;
if(readCount == 0) •First reader competes with writers
V(writeBlock); •Last reader signals writers
V(mutex);
}
}
resourceType *resource;
int readCount = 0;
semaphore mutex = 1;
semaphore writeBlock = 1;
fork(reader, 0);
fork(writer, 0);
First Solution
reader() { writer() {
while(TRUE) { while(TRUE) {
<other computing>; <other computing>;
P(mutex); P(writeBlock);
readCount++; /* Critical section */
if(readCount == 1) access(resource);
P(writeBlock); V(writeBlock);
V(mutex); }
/* Critical section */ }
access(resource);
P(mutex);
readCount--;
if(readCount == 0) •First reader competes with writers
V(writeBlock); •Last reader signals writers
V(mutex);
} •Any writer must wait for all readers
} •Readers can starve writers
resourceType *resource;
int readCount = 0; •“Updates” can be delayed forever
semaphore mutex = 1; •May not be what we want
semaphore writeBlock = 1;
fork(reader, 0);
fork(writer, 0);
Precedence to writer process
34
reader() {
Writer Precedence writer() {
while(TRUE) { while(TRUE) {
<other computing>; <other computing>;
4 P(writePending); P(mutex2);
P(readBlock); writeCount++;
P(mutex1); if(writeCount == 1)
readCount++; 3 P(readBlock);
2 if(readCount == 1) V(mutex2);
P(writeBlock); P(writeBlock);
V(mutex1); access(resource);
V(readBlock); V(writeBlock);
1 V(writePending); P(mutex2)
access(resource); writeCount--;
P(mutex1); if(writeCount == 0)
readCount--; V(readBlock);
if(readCount == 0) V(mutex2);
V(writeBlock); }
V(mutex1); }
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1, writePending = 1;
fork(reader, 0);
fork(writer, 0);
Implementing Semaphores: Test and Set Instruction
• “TS R3, m “ loads register R3 tests its value and writes a TRUE back to location m.
• OS function - TS(m): [Reg_i = memory[m]; memory[m] = TRUE;]
Data CC Data CC
Register Register Register Register
R3 … … R3 FALSE =0
m FALSE m TRUE
Primary Primary
Memory Memory