0% found this document useful (0 votes)
6 views73 pages

L02 Processes Threads

The document outlines the concepts of processes, threads, and synchronization in programming, detailing the steps for program parallelization, including decomposition, scheduling, and mapping. It explains the characteristics of processes and threads, their creation, communication, and the importance of synchronization to manage shared resources and prevent race conditions. Additionally, it discusses various mechanisms for controlling access to shared resources, such as locks and semaphores.

Uploaded by

Vishnu Prasath
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views73 pages

L02 Processes Threads

The document outlines the concepts of processes, threads, and synchronization in programming, detailing the steps for program parallelization, including decomposition, scheduling, and mapping. It explains the characteristics of processes and threads, their creation, communication, and the importance of synchronization to manage shared resources and prevent race conditions. Additionally, it discusses various mechanisms for controlling access to shared resources, such as locks and semaphores.

Uploaded by

Vishnu Prasath
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 73

Processes, Threads, and

Synchronization

Lecture 02
Program Parallelization: Steps
Done by programmer
 3 main steps: Sequential
Algorithm
1. Decomposition of the decompose
computations
Tasks
2. Scheduling (assignment of schedule
tasks to processes (or
threads)) Processes
or Threads
map
3. Mapping of processes (or
threads) to physical processors Physical Cores
(or cores) & Processors
[ CS3210 - AY2425S1 - L02 ]
2
Program Parallelization: Steps
 3 main steps: Sequential
Algorithm
1. Decomposition of the decompose
computations
Tasks
2. Scheduling (assignment of
Done by OS &schedule
libraries*
tasks to processes (or
threads)) Processes
or Threads
map
3. Mapping of processes (or
threads) to physical Physical Cores
processors (or cores) & Processors
[ CS3210 - AY2425S1 - L02 ]
3
Abstractions of flow of control

PROCESSES AND THREADS

[ CS3210 - AY2425S1 - L02 ]


4
Processes
 An instance of a program in execution
 Identified by PID (process ID)
 Comprises:
 executable program (PC),
 global data
 OS resources: open files, network connections
 stack or heap
 current values of the registers (GPRs and Special)
 Own address space  exclusive access to its data
 Two or more processes exchange data  need explicit
communication

[ CS3210 - AY2425S1 - L02 ]


5
Memory Illustration of a Process
Text
(for instructions)

Data
(for global variables)
The entire
memory Heap
space (for dynamic allocation)

Stack
(for function invocations)

[ CS3210 - AY2425S1 - L02 ]


6
Multi-Programming (Multitasking)
 Several processes at different stages of execution
 Need context switch, i.e., switching between processes

 States of the suspended process must be saved  overhead

 2 types of execution:
 Time slicing execution – pseudo-parallelism
 Parallel execution of processes on different resources

[ CS3210 - AY2425S1 - L02 ]


7
Create a New Process in Unix
 Process P1 can create a new process P2
 fork system call
 int exec(char *prog, char *argv[])
 P2 is an identical copy of P1 at the time of the fork call
 P2 works on a copy of the address space of P1
 P2 executes the same program as P1, starting with the instruction
following the fork call
 P2 gets its own process number
 Use ps or top in Unix console to see a list of processes
 P2 can execute different statements as P1

[ CS3210 - AY2425S1 - L02 ]


8
Fork()
int main(int argc, char *argv[])
{
char *name = argv[0];
int child_pid = fork();
if (child_pid == 0) {
printf(“Child of %s is %d\n”, name, getpid());
return 0;
} else {
printf(“My child is %d\n”, child_pid);
return 0;
}
}

[ CS3210 - AY2425S1 - L02 ]


9
Process State Graph

[ CS3210 - AY2425S1 - L02 ]


10
Why fork()?
 Very useful when the child…
 Is cooperating with the parent
 Relies upon the parent’s data to accomplish its task
 Example: web server
while(1) {
int sock =accept();
if ((child_pid = fork()) == 0){
Child process executes this branch: Handles client request
} else {
Parent process executes this branch: Closes socket

}}

[ CS3210 - AY2425S1 - L02 ]


11
Process Termination
 Use exit(status) in the child process
 Wait for a process in the parent process
 wait
 waitpid (pid)

[ CS3210 - AY2425S1 - L02 ]


12
Inter-process Communication (IPC)
 Cooperating processes have to share information
 Shared memory
 Need to protect access when reading/writing with locks
 Message passing
 Blocking & non-blocking
 Synchronous & asynchronous
 Unix specific:
 Pipes & Signal

[ CS3210 - AY2425S1 - L02 ]


13
Process Interaction with OS
Exceptions Interrupts
 Executing a machine level  External events can interrupt the

instruction can cause exception execution of a program


 For example: Overflow, Underflow,  Usually hardware related: Timer,

Division by Zero, Illegal memory address, Mouse Movement, Keyboard


Mis-aligned memory access Pressed etc

 Synchronous  Asynchronous
 Occur due to program execution  Occur independently of program
 Have to execute an exception execution
handler  Have to execute an interrupt
handler

[ CS3210 - AY2425S1 - L02 ]


14
Disadvantages of Processes
 Creating a new process is costly
 Overhead of system calls
 All data structures must be allocated, initialized and copied
 Communicating between processes costly
 Communication goes through the OS

[ CS3210 - AY2425S1 - L02 ]


15
Threads
 Extension of process model:
 A process may consist of multiple independent control flows called
threads
 The thread defines a sequential execution stream within a
process(PC, SP, registers)
 Threads share the address space of the process:
 All threads belonging to the same process see the same value 
shared-memory architecture

[ CS3210 - AY2425S1 - L02 ]


16
Process and thread: Illustration

 Taken from Operating System Concepts (7th Edition) by Silberschatz, Galvin & Gagne, published by Wiley

[ CS3210 - AY2425S1 - L02 ]


17
Threads (cont)
 Thread generation is faster than process generation
 No copy of the address space is necessary

 Different threads of a process can be assigned run on


different cores of a multicore processor

 2 types of threads
 User-level threads
 Kernel threads

[ CS3210 - AY2425S1 - L02 ]


18
User-Level Threads
 Managed by a thread library – OS unaware of user-level
threads so no OS support

 Advantages – switching thread context is fast

 Disadvantages
 OS cannot map different threads of the same process to different
execution resources  no parallelism
 OS cannot switch to another thread if one thread executes a blocking
I/O operation

[ CS3210 - AY2425S1 - L02 ]


19
Kernel Threads
 OS is aware of the existence of threads and can react
correspondingly

 Avoid disadvantages of user-level threads

 Efficient use of the cores in a multicore system

[ CS3210 - AY2425S1 - L02 ]


20
Many-to-One Mapping
 All user-level threads are
mapped to one process

 Thread library is
responsible for the
scheduling of user-level
threads

[ CS3210 - AY2425S1 - L02 ]


21
One-to-One Mapping
 Each user-level thread is
assigned to exactly one kernel
thread - no library scheduler
needed

 OS is responsible for the


scheduling and mapping of
kernel threads

[ CS3210 - AY2425S1 - L02 ]


22
Many-to-Many Mapping
 Library scheduler assigns the user-level threads to a given set
of kernel threads
 Kernel scheduler maps the kernel threads to the available
execution resources
 At different points in
time, a user thread
may be mapped to a
different kernel thread

[ CS3210 - AY2425S1 - L02 ]


23
Visibility of Data
 Global variables of a program and all dynamically allocated
data objects can be accessed by any thread of this process
Text
(for instructions)
Data
 Each thread has a private (for global variables)
Heap
runtime stack for function (for dynamic allocation)
stack frames The entire
memory
space
Stack frame for thread 2
 Runtime stack of a thread
exists iff the thread Stack frame for thread 1
is active
Stack frame main thread
(for function invocations)
[ CS3210 - AY2425S1 - L02 ]
24
POSIX Threads
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_message_function( void *ptr );
main()
{
pthread_t thread1, thread2;
char *message1 = "Thread 1";
char *message2 = "Thread 2";
int iret1, iret2;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);

/* Wait till threads are complete before main continues. Unless we */


/* wait we run the risk of executing an exit which will terminate */
/* the process and all threads before the threads have completed. */
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);

printf("Thread 1 returns: %d\n",iret1);


printf("Thread 2 returns: %d\n",iret2);
exit(0);
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}
[ CS3210 - AY2425S1 - L02 ]
25
Number of Threads
 Number of threads should be
 Suitable to parallelism degree of application
 Suitable to available execution resources
 Not be too large to keep low the overhead for thread creation,
management, and termination small

[ CS3210 - AY2425S1 - L02 ]


26
SYNCHRONIZATION

[ CS3210 - AY2425S1 - L02 ]


27
Introduction
 Threads cooperate in multithreaded programs
 Share resources, access shared data structures
 Coordinate their execution
 One thread executes relative to another
 For correctness, control this cooperation
 Threads interleave executions arbitrarily and at different rates
 Scheduling is not under program control
 Use synchronization
 Restrict the possible interleaving of thread executions
*Discuss in terms of threads, also applies to processes

[ CS3210 - AY2425S1 - L02 ]


28
Shared Resources
 Coordinating access to shared resources
 Basic problem:
 If two concurrent threads (processes) are accessing a shared variable, and
that variable is read/ modified/ written by those threads, then access to the
variable must be controlled to avoid erroneous behaviour
 Mechanisms to control access to shared resources
 Locks, mutexes, semaphores, monitors, condition variables, etc.
 Patterns for coordinating accesses to shared resources
 Bounded buffer, producer-consumer, etc.

[ CS3210 - AY2425S1 - L02 ]


29
Classic Example
 Implement a function to handle withdrawals from a bank
account:
withdraw (account, amount) {
balance = get_balance(account);
balance = balance – amount;
put_balance(account, balance);
return balance;
}
 2 people share a bank account with a balance of $1000
 Simultaneously withdraw $100 from the account

[ CS3210 - AY2425S1 - L02 ]


30
Classic Example - Threading
 Create a thread for each person to do the withdrawals
 These threads run on the same bank server:

 Possible problems?

[ CS3210 - AY2425S1 - L02 ]


31
Classic Example - Problem
 Execution of the two threads can be interleaved

[ CS3210 - AY2425S1 - L02 ]


32
Race condition
 Race condition happens when multiple execution paths (of
different threads or processes) executing at the same time
finish in a different order than expected
 May cause software bugs due to unanticipated behavior
 Actual behavior is different from designed behavior due to timings
and instruction interleavings caused by concurrency
 Critical race conditions cause invalid execution and software
bugs
 Usually happen when the processes or threads depend on some
shared state
 Use critical sections to make the operations upon shared states
mutually exclusive
[ CS3210 - AY2425S1 - L02 ]
33
Critical section
 Use a critical section to protect the parts of the program
where the shared resource is accessed to avoid concurrent
access
 This protected section
 cannot be entered by more than one process or thread at a time; and
 others are suspended until the first leaves the critical section
 A critical section is a region of code that requires mutual
exclusion
 Typically, the critical section accesses a shared resource,
such as a data structure, peripheral device, or network
connection, that would not operate correctly in the context of
multiple concurrent accesses
[ CS3210 - AY2425S1 - L02 ]
35
Mutual Exclusion
 Use mutual exclusion to protect access to shared resources
(to implement critical sections)
 One thread of execution never enters a critical section while a
concurrent thread of execution is already accessing said critical
section
 Only one thread at a time can execute in the critical section
 All other threads have to wait on entry
 When a thread leaves a critical section, another can enter

[ CS3210 - AY2425S1 - L02 ]


36
Data Race (a type of race condition)
1. Two concurrent threads (or processes) access a shared
resource (memory location) without any protection
AND
2. At least one thread modifies the shared resource
 Solution: control access to these shared resources

 Necessary to synchronize access to any shared data


structure
 Buffers, queues, lists, hash tables, etc.

[ CS3210 - AY2425S1 - L02 ]


37
Mechanisms
 Locks
 Primitive, minimal semantics, used to build others
 Semaphores
 Basic, easy to get the hang of, but hard to program with
 Monitors
 High-level, requires language support, operations implicit
 Messages
 Simple model of communication and synchronization based on
transfer of data across a channel
 Direct application to distributed systems
 Messages for synchronization are straightforward (once we see how
the others work)
[ CS3210 - AY2425S1 - L02 ]
38
Locks
 Two operations
 acquire(): to enter a critical section
 release(): to leave a critical section
 Pair calls to acquire and release
 Between acquire/release, the thread holds the lock
 Acquire does not return until any previous holder releases
 What can happen if the calls are not paired?
 Locks can spin (a spinlock) or block (a mutex)

[ CS3210 - AY2425S1 - L02 ]


39
Using Locks

[ CS3210 - AY2425S1 - L02 ]


40
Semaphores
 Semaphores are an abstract data type that provide mutual
exclusion through atomic counters
 Described by Dijkstra in the “THE” system in 1968
 Semaphores are “integers” that support two operations:
 Semaphore::Wait(): decrement, block until semaphore is open
 Also P(), after the Dutch word for “try to reduce” (down)
 Semaphore::Signal(): increment, allow another thread to enter
 Also V() after the Dutch word for increment (up)
 Semaphore safety property: the semaphore value is always greater
than or equal to 0

[ CS3210 - AY2425S1 - L02 ]


41
Semaphore Types
 Mutex semaphore (or binary semaphore)
 Represents single access to a resource
 Guarantees mutual exclusion to a critical section
 Counting semaphore (or general semaphore)
 Multiple threads can pass the semaphore
 Number of threads determined by the semaphore “count”
 mutex has count = 1, counting has count = N

[ CS3210 - AY2425S1 - L02 ]


42
Example

[ CS3210 - AY2425S1 - L02 ]


43
Semaphores Summary
 Semaphores can be used as a mutex
 However, they have some drawbacks
 They are essentially shared global variables
 Can potentially be accessed anywhere in program
 No connection between the semaphore and the data being controlled
by the semaphore
 Used both for critical sections (mutual exclusion) and coordination
(scheduling)
 Sometimes hard to use and prone to bugs

[ CS3210 - AY2425S1 - L02 ]


44
Barrier

[ CS3210 - AY2425S1 - L02 ]


45
Deadlock
 Definition:
 Deadlock exists among a set of processes if every process is waiting
for an event that can be caused only by another process in the set.
 Deadlock is a problem that can arise:
 When processes compete for access to limited resources
 When processes are incorrectly synchronized

[ CS3210 - AY2425S1 - L02 ]


47
Condition for Deadlock
 Deadlock can exist if and only if the following four conditions
hold simultaneously:
1. Mutual exclusion – At least one resource must be held in a non-
sharable mode
2. Hold and wait – There must be one process holding one resource
and waiting for another resource
3. No pre-emption – Resources cannot be pre-empted (critical
sections cannot be aborted externally)
4. Circular wait – There must exist a set of processes [P1, P2,
P3,…,Pn] such that P1 is waiting for P2, P2 for P3, etc., Pn for P1

[ CS3210 - AY2425S1 - L02 ]


48
Dealing with Deadlock
 There are four approaches for dealing with deadlock:
 Ignore it–how lucky do you feel?
 Prevention–make it impossible for deadlock to happen
 Avoidance–control allocation of resources
 Detection and recovery–look for a cycle in dependencies

[ CS3210 - AY2425S1 - L02 ]


49
Starvation
 Starvation is a situation where a process is prevented from
making progress because some other process has the
resource it requires
 Starvation is a side effect of the scheduling algorithm
 OS: A high priority process always prevents a low priority process
from running on the processing unit
 One thread always beats another when acquiring a lock

[ CS3210 - AY2425S1 - L02 ]


50
Livelock
 Similar to a deadlock
 The states of the processes involved in the livelock constantly
change with regard to one another, none progressing
 Special case of resource starvation
 A specific thread or process is not progressing

[ CS3210 - AY2425S1 - L02 ]


52
CLASSICAL SYNCHRONIZATION PROBLEMS

[ CS3210 - AY2425S1 - L02 ]


53
Classic Synchronization Problems
 Producer-consumer
 Infinite buffer
 Finite buffer
 Readers-writers
 Dining philosophers
 Barbershop
 …

[ CS3210 - AY2425S1 - L02 ]


54
Producer-consumer
 Producers create items of some kind and add them to a data
structure
 Consumers remove the items and process them
 Variables:
 mutex = Semaphore (1)
 items = Semaphore (0)

[ CS3210 - AY2425S1 - L02 ]


55
Producer-consumer

Producer Consumer
 event = waitForEvent ()  items.wait ()

 mutex.wait ()  mutex.wait ()
 buffer.add ( event )  event = buffer.get ()
 items.signal ()  mutex.signal ()
 mutex.signal ()  event.process ()

[ CS3210 - AY2425S1 - L02 ]


56
Improved Producer-consumer

Producer Consumer
 event = waitForEvent ()  items.wait ()

 mutex.wait ()  mutex.wait ()
 buffer.add ( event )  event = buffer.get ()
 mutex.signal ()  mutex.signal ()
 items.signal ()  event.process ()

[ CS3210 - AY2425S1 - L02 ]


57
Improved Producer-consumer

Producer Consumer
 event = waitForEvent ()  items.wait ()

 mutex.wait ()  mutex.wait ()
 buffer.add ( event )  event = buffer.get ()
 mutex.signal ()  mutex.signal ()
 items.signal ()  event.process ()

[ CS3210 - AY2425S1 - L02 ]


58
Broken Producer-consumer

Producer Consumer
 event = waitForEvent ()  mutex.wait ()

 mutex.wait ()  items.wait ()
 buffer.add ( event )  event = buffer.get ()
 mutex.signal ()  mutex.signal ()
 items.signal ()  event.process ()

[ CS3210 - AY2425S1 - L02 ]


59
Producer-consumer with Finite Buffer

Producer Consumer
 event = waitForEvent ()  items.wait ()

 spaces.wait ()  mutex.wait ()

 mutex.wait ()  event = buffer.get ()


 buffer.add ( event )  mutex.signal ()
 mutex.signal ()  spaces.signal ()
 items.signal ()  event.process ()

[ CS3210 - AY2425S1 - L02 ]


60
Readers-writers Problem
 Any number of readers can be in the critical section
simultaneously
 Writers must have exclusive access to the critical section
 Variables:
 int readers = 0
 mutex = Semaphore (1)
 roomEmpty = Semaphore (1)

[ CS3210 - AY2425S1 - L02 ]


61
Readers-writers

Writers Readers
 roomEmpty.wait ()  mutex.wait ()
 #critical section for writers  readers += 1
 if readers == 1:
 roomEmpty.signal ()  roomEmpty.wait () # first in locks
 mutex.signal ()
 # critical section for readers
 mutex.wait ()
 readers -= 1
 if readers == 0:
 roomEmpty.signal () # last out unlocks
 mutex.signal ()

[ CS3210 - AY2425S1 - L02 ]


62
Lightswitch Definition
class Lightswitch :
 def __init__ ( self ):
 self.counter = 0
 self.mutex = Semaphore (1)
 def lock (self , semaphore ):
 self.mutex.wait ()
 self.counter += 1
 if self.counter == 1:
 semaphore.wait ()
 self.mutex.signal ()
 def unlock (self , semaphore ):
 self.mutex.wait ()
 self.counter -= 1
 if self.counter == 0:
 semaphore.signal ()
 self.mutex.signal ()
[ CS3210 - AY2425S1 - L02 ]
63
Readers-writers with Lightswitch

Writers Readers
 roomEmpty.wait ()  readLightswitch.lock (roomEmpty )
 #critical section for writers  # critical section
 roomEmpty.signal ()  readLightswitch.unlock (roomEmpty)

 #starving writers
 Use a
 turnstile = Semaphore (1)

[ CS3210 - AY2425S1 - L02 ]


64
No-starve Readers-writers

Writers Readers
 turnstile.wait ()  turnstile.wait ()
 roomEmpty.wait ()  turnstile.signal ()
# critical section for writers
 readSwitch.lock ( roomEmpty )

 turnstile.signal ()  # critical section for readers


 roomEmpty.signal ()  readSwitch.unlock ( roomEmpty )

[ CS3210 - AY2425S1 - L02 ]


65
Readers-writers with Priorities

Writers Readers
 writeSwitch.lock (noReaders)  noReaders.wait ()
 noWriters.wait ()  readSwitch.lock (noWriters)
 # critical section for writers  noReaders.signal ()
noWriters.signal()

 # critical section for readers
 writeSwitch.unlock (noReaders)  readSwitch.unlock ( noWriters )

[ CS3210 - AY2425S1 - L02 ]


66
Summary
 We discussed the parts of the OS that impact the parallel
computing field
 Processes, threads, and their overheads
 Synchronization and classical synchronization problems

[ CS3210 - AY2425S1 - L02 ]


67
Readings
 Any operating system textbook; CS2106
 CSE 120: Principles of Computer Operating Systems, UCSD,
http://cseweb.ucsd.edu/classes/fa16/cse120-a/
 The Little Book of Semaphores by Allen Downey,
hsttp://greenteapress.com/semaphores/LittleBookOfSemapho
res.pdf

[ CS3210 - AY2425S1 - L02 ]


68
LOCK IMPLEMENTATION

[ CS3210 - AY2425S1 - L02 ]


69
Implementing Locks (1)
 An attempt:

 This is called a spinlock because a thread spins waiting for


the lock to be released
 Does this work?
[ CS3210 - AY2425S1 - L02 ]
70
Implementing Locks (2)
 No. Two independent threads may both notice that a lock has
been released and thereby acquire it.

[ CS3210 - AY2425S1 - L02 ]


71
Implementing Locks (3)
 The problem: implementation of locks has critical sections,
too
 How do we stop the recursion?
 The implementation of acquire/release must be atomic
 An atomic operation is one which executes as though it could not be
interrupted
 Code that executes “all or nothing”
 Need help from hardware
 Atomic instructions (e.g., test-and-set)
 Disable/enable interrupts (prevents context switches)

[ CS3210 - AY2425S1 - L02 ]


72
Atomic Instructions: Test-and-set
 The semantics of test-and-set are:
 Record the old value
 Set the value to indicate available
 Return the old value
 Hardware executes it atomically!

[ CS3210 - AY2425S1 - L02 ]


73
Lock with Test-and-set

[ CS3210 - AY2425S1 - L02 ]


74
Problems with Spinlocks
 Spinlocks are wasteful
 If a thread is spinning on a lock, then the thread holding the lock
cannot make progress (on a uniprocessor)
 How did the lock holder give up the processing unit in the first
place?
 Lock holder calls yield or sleep
 Involuntary context switch

[ CS3210 - AY2425S1 - L02 ]


75
Higher-level Synchronization
 All synchronization requires atomicity
 Use “atomic”
 Look at two common high-level mechanisms
 Semaphores: binary (mutex) and counting
 Monitors: mutexes and condition variables locks as primitives

[ CS3210 - AY2425S1 - L02 ]


76

You might also like