Threads: Single and Multithreaded Processes
Threads: Single and Multithreaded Processes
Threads: Single and Multithreaded Processes
• Overview
• Multithreading Models
• Threading Issues
• Pthreads
• Solaris 2 Threads
• Windows 2000 Threads
• Linux Threads
• Java Threads
Benefits
• Responsiveness
• Resource Sharing
• Economy
• Utilization of MP Architectures
User Threads
Kernel Threads
Multithreading Models
• Many-to-One
• One-to-One
• Many-to-Many
Many-to-One
• Many user-level threads mapped to single kernel thread.
• Used on systems that do not support kernel threads.
One-to-On
Many-to-Many Model
Threading Issues
Pthreads
• a POSIX standard (IEEE 1003.1c) API for thread creation and synchronization.
• API specifies behavior of the thread library, implementation is up to development
of the library.
• Common in UNIX operating systems.
Solaris 2 Threads
Solaris Process
Linux Threads
Java Threads
Basic Concepts
CPU Scheduler
• Selects from among the processes in memory that are ready to execute, and
allocates the CPU to one of them.
• CPU scheduling decisions may take place when a process:
Switches from running to waiting state.
Switches from running to ready state.
Switches from waiting to ready.
Terminates.
• Scheduling under 1 and 4 is nonpreemptive.
• All other scheduling is preemptive.
Dispatcher
• Dispatcher module gives control of the CPU to the process selected by the short-
term scheduler; this involves:
✦ switching context
✦ switching to user mode
✦ jumping to the proper location in the user program to restart that program
• Dispatch latency – time it takes for the dispatcher to stop one process and start
another running.
Scheduling Criteria
Optimization Criteria
P1 P2 P3
0 24 27 30
• Waiting time for P1 = 0; P2 = 24; P3 = 27
• Average waiting time: (0 + 24 + 27)/3 = 17
Suppose that the processes arrive in the order
P2 , P3 , P1 .
• The Gantt chart for the schedule is:
P2 P3 P1
0 3 6 30
• Associate with each process the length of its next CPU burst. Use these lengths to
schedule the process with the shortest time.
• Two schemes:
✦ nonpreemptive – once CPU given to the process it cannot be preempted
until completes its CPU burst.
✦ preemptive – if a new process arrives with CPU burst length less than
remaining time of current executing process, preempt. This scheme is
know as the
Shortest-Remaining-Time-First (SRTF).
• SJF is optimal – gives minimum average waiting time for a given set of processes.
• SJF (non-preemptive)
P1 P3 P2 P4
0 3 7 8 12 16
• Average waiting time = (0 + 6 + 3 + 7)/4 - 4
• SJF (preemptive)
P1 P2 P3 P2 P4 P1
0 2 4 5 7 11 16
τ n =1 = α tn + (1 − α )τ n .
Prediction of the Length of the Next CPU Burst
• α =0
✦ τ n+1 = τ n
✦ Recent history does not count.
• α =1
✦ τ n+1 = tn
✦ Only the actual last CPU burst counts.
• If we expand the formula, we get:
τ n+1 = α tn+(1 - α ) α tn -1 + …
+(1 - α )j α tn -1 + …
+(1 - α )n=1 tn τ 0
• Since both α and (1 - α ) are less than or equal to 1, each successive term has
less weight than its predecessor.
Priority Scheduling
• Each process gets a small unit of CPU time (time quantum), usually 10-100
milliseconds. After this time has elapsed, the process is preempted and added to
the end of the ready queue.
• If there are n processes in the ready queue and the time quantum is q, then each
process gets 1/n of the CPU time in chunks of at most q time units at once. No
process waits more than (n-1)q time units.
• Performance
✦ q large ⇒ FIFO
✦ q small ⇒ q must be large with respect to context switch, otherwise
overhead is too high.
P1 P2 P3 P4 P1 P3 P4 P1 P3 P3
2 3 5 7 9 11 12 13 15 16
0
0 7 7 7 7 7 1 4 4 2
• Typically, higher average turnaround than SJF, but better response.
Time Quantum and Context Switch Time
• A process can move between the various queues; aging can be implemented this
way.
• Multilevel-feedback-queue scheduler defined by the following parameters:
✦ number of queues
✦ scheduling algorithms for each queue
✦ method used to determine when to upgrade a process
✦ method used to determine when to demote a process
✦ method used to determine which queue a process will enter when that
process needs service
• Three queues:
✦ Q0 – time quantum 8 milliseconds
✦ Q1 – time quantum 16 milliseconds
✦ Q2 – FCFS
• Scheduling
✦ A new job enters queue Q0 which is served FCFS. When it gains CPU, job
receives 8 milliseconds. If it does not finish in 8 milliseconds, job is
moved to queue Q1.
✦ At Q1 job is again served FCFS and receives 16 additional milliseconds.
If it still does not complete, it is preempted and moved to queue Q2.
Real-Time Scheduling
Dispatch Latency
Algorithm Evaluation
Background
Concurrent access to shared data may result in data inconsistency.
Maintaining data consistency requires mechanisms to ensure the orderly
execution of cooperating processes.
Shared-memory solution to bounded-butter problem (Chapter 4) allows at most n
– 1 items in buffer at the same time. A solution, where all N buffers are used is
not simple.
✦ Suppose that we modify the producer-consumer code by adding a variable
counter, initialized to 0 and incremented each time a new item is added to
the buffer
Bounded-Buffer
Shared data
#define BUFFER_SIZE 10
typedef struct {
...
} item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
int counter = 0;
Producer process
item nextProduced;
while (1) {
while (counter == BUFFER_SIZE)
; /* do nothing */
buffer[in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
counter++;
}
Consumer process
item nextConsumed;
while (1) {
while (counter == 0)
; /* do nothing */
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
counter--;
}
The statements
counter++;
counter--;
must be performed atomically.
register1 = counter
register1 = register1 + 1
counter = register1
register2 = counter
register2 = register2 – 1
counter = register2
If both the producer and consumer attempt to update the buffer concurrently, the
assembly language statements may get interleaved.
Interleaving depends upon how the producer and consumer processes are
scheduled.
Assume counter is initially 5. One interleaving of statements is:
The value of count may be either 4 or 6, where the correct result should be 5.
Race Condition
■ Race condition: The situation where several processes access – and manipulate
shared data concurrently. The final value of the shared data depends upon which
process finishes last.
return rv;
}
Mutual Exclusion with Test-and-Set
■ Shared data:
boolean lock = false;
■ Process Pi
do {
while (TestAndSet(lock)) ;
critical section
lock = false;
remainder section
}
Synchronization Hardware
■ Atomically swap two variables.
void Swap(boolean &a, boolean &b) {
boolean temp = a;
a = b;
b = temp;
}
Mutual Exclusion with Swap
■ Shared data (initialized to false):
boolean lock;
boolean waiting[n];
■ Process Pi
do {
key = true;
while (key == true)
Swap(lock,key);
critical section
lock = false;
remainder section
}
Semaphores
■ Synchronization tool that does not require busy waiting.
■ Semaphore S – integer variable
■ can only be accessed via two indivisible (atomic) operations
wait (S):
while S≤ 0 do no-op;
S--;
signal (S):
S++;
Critical Section of n Processes
■ Shared data:
semaphore mutex; //initially mutex = 1
■ Process Pi:
do {
wait(mutex);
critical section
signal(mutex);
remainder section
} while (1);
Semaphore Implementation
■ Define a semaphore as a record
typedef struct {
int value;
struct process *L;
} semaphore;
■ Assume two simple operations:
✦ block suspends the process that invokes it.
✦ wakeup(P) resumes the execution of a blocked process P.
Implementation
■ Semaphore operations now defined as
wait(S):
S.value--;
if (S.value < 0) {
add this process to S.L;
block;
}
signal(S):
S.value++;
if (S.value <= 0) {
remove a process P from S.L;
wakeup(P);
}
Semaphore as a General Synchronization Tool
■ Execute B in Pj only after A executed in Pi
■ Use semaphore flag initialized to 0
■ Code:
Pi Pj
Μ Μ
A wait(flag)
signal(flag) B
Deadlock and Starvation
■ Deadlock – two or more processes are waiting indefinitely for an event that can
be caused by only one of the waiting processes.
■ Let S and Q be two semaphores initialized to 1
P0 P1
wait(S); wait(Q);
wait(Q); wait(S);
Μ Μ
signal(S); signal(Q);
signal(Q) signal(S);
■ Starvation – indefinite blocking. A process may never be removed from the
semaphore queue in which it is suspended.
Two Types of Semaphores
■ Counting semaphore – integer value can range over an unrestricted domain.
■ Binary semaphore – integer value can range only between 0 and 1; can be simpler
to implement.
■ Can implement a counting semaphore S as a binary semaphore
Implementing S as a Binary Semaphore
■ Data structures:
binary-semaphore S1, S2;
int C:
■ Initialization:
S1 = 1
S2 = 0
C = initial value of semaphore S
Implementing S
■ wait operation
wait(S1);
C--;
if (C < 0) {
signal(S1);
wait(S2);
}
signal(S1);
■ signal operation
wait(S1);
C ++;
if (C <= 0)
signal(S2);
else
signal(S1);
Classical Problems of Synchronization
■ Bounded-Buffer Problem
■ Readers and Writers Problem
■ Dining-Philosophers Problem
Bounded-Buffer Problem
■ Shared data
Initially:
Initially
void putdown(int i) {
state[i] = thinking;
// test left and right neighbors
test((i+4) % 5);
test((i+1) % 5);
}
Dining Philosophers
void test(int i) {
if ( (state[(I + 4) % 5] != eating) &&
(state[i] == hungry) &&
(state[(i + 1) % 5] != eating)) {
state[i] = eating;
self[i].signal();
}
}
x-count++;
if (next-count > 0)
signal(next);
else
signal(mutex);
wait(x-sem);
x-count--;