10 What is difference between Process and Threads

CMSC621: Advanced Operating Systems
Nilanjan Banerjee
Associate Professor, University of Maryland
Baltimore County
[email protected]
http://www.csee.umbc.edu/~nilanb/teaching/621/
Advanced Operating Systems
1
Announcements
• Project 1 will be given out next week.
• How did the homework go?
2
Short homework
• Assume that a mmapped file has four
numbers (1) a (2) b (3) c (4) sum =
a+b+c
• Three processes are executed.
–
–
–
–
First process increments a
Second process increments b
Third process increments c
Each time one of the above happens sum is
updated
• Add proper mutual exclusion to ensure
that sum is always equal to a+b+c.
3
Message Passing Using Sockets
• A socket is defined as an endpoint for
communication
• Concatenation of IP address and port
• The socket 161.25.19.8:1625 refers to port
1625 on host 161.25.19.8
• Communication consists between a pair of
sockets
4
Message Passing Using Sockets
5
POSIX Signals
Linux kernel
Process 1
Process 2
Register a
signal

Name
SIGINT
SIGQUIT
SIGKILL
SIGSEGV
SIGPIPE
SIGALRM
SIGUSR1
SIGUSR2
deliver
a signal
Description
Default Action
Interrupt character typed terminate process
Quit character typed (^\) create core image
kill -9
terminate process
Invalid memory reference create core image
Write on pipe but no reader terminate process
alarm() clock ‘rings’
terminate process
user-defined signal type terminate process
user-defined signal type terminate process
6
signals
• int kill( pid_t pid, int signo );
– Send a signal to a process with a process id
• signal(<signal name>, <pointer to
handler>)
– Handle a maskable signal in your code
7
Why do we need processes?

A process (with a single thread) supports a serial flow of execution

Is that good enough for all purposes?

What if something goes wrong in one process?

What if something takes a long amount of time in one process?

What if we have more than one user?
8
What is difference between Process and Threads

The execution context of the process are (Program Counter,
registers), address space, files, mmaped regions etc.
9
What is difference between Process and Threads

Threads share an address space. They have same files, sockets etc.

They have their own stack, program counters, registers, and stack
specific data
10
Threads Vs Processes


Processes or Threads

Performance?

Flexibility/Ease-of-use

Robustness
Simple Scheduling

OS has a list of Threads and schedules them similar to
Processes. In Linux, threads/processes treated similarly

Chooses one of the threads and loads them to be run

Runs them for a while, runs another.
11
Flexibility/Ease of use?


Process are more flexible

Easy to spawn processes, I can ssh into a server and spawn a
process

Can communicate over sockets= distributes across machines
Threads

Communicate using memory – must be on the same machine

Requires thread-safe code
12
Robustness


Process are more robust

Processes are separate or sandboxed from other processes

If one process dies, no effect on other processes
Threads

If one thread crashes, whole process terminates

Since there is sharing, there are problems with using the stack
efficiently
13
Creating Threads

UNIX

Pthreads (POSIX threads)

Pthread_create() --- creating a thread

Pthread_join() --- wait for thread to finish
Lets see a demonstration of using pthreads.
14
Context Switch cost
 Threads – much cheaper
– Stash registers, PC (“IP”), stack pointer
 Processes – above plus
– Process context
– TLB shootdown
 Process switches more expensive, or
require long quanta
15
Synchronization and Concurrency
 Probably the MOST important concept in OS
Lets look at a demonstration
16
What really happened?
Count = count + 1
load X R1
add Y Z R1
store Y in Mem
Thread 1 executes
the first two
statements
and is preempted…
Thread 2
executes all the
three statements
Thread 1 returns
and executes the
third statement
17
Concurrency Terminology
 Mutual exclusion (“mutex”)
– prevents multiple threads from entering
 Critical section
– code only one thread can execute at a time
 Lock
– mechanism for mutual exclusion
– Lock entering critical section, accessing shared
data
– Unlock when complete
– Wait if locked
 Invariant
– Something that must be true
18
Why do we need concurrency?
 Synchronization serves two purposes:
– Ensure safety for shared updates
• Avoid race conditions
– Coordinate actions of threads
• Parallel computation
• Event notification
 ALL interleavings must be correct
– there are lots of interleavings of events
– also constrain as little as possible
19
Locks/mutexes
 Provide mutual exclusion to shared data
– Two routines
• acquire – wait for lock, then take it
• release – unlock, wake up waiters
 Rules:
– Acquire lock before accessing shared data
– Release lock afterwards
– Lock initially released
20
Locks and Queueing
• Acquire:
– if unlocked,
go in;
otherwise wait in
line
• Release:
– Unlock & leave
21
Synchronization and Concurrency
Demonstration on using pthread locks/mutexes
22
Safety
 Locks can enforce mutual exclusion,
but notorious source of errors
–
–
–
–
Failure to unlock
Double locking
Deadlock (its own lecture)
Priority inversion
• not an “error” per se
pthread_mutex_t l;
void square (void) {
pthread_mutex_lock (&l);
// acquires lock
// do stuff
if (x == 0) {
return;
} else {
x = x * x;
}
pthread_mutex_unlock (&l);
}
23
Bounded Buffer or Producer Consumer Problem
 Suppose we have a thread-safe queue
– insert(item), remove(), empty()
– must protect access with locks
 Consumer
 Consumes items in the queue
 Only if queue has items
 Producer:
 Produces items
 Adds them only if the queue is not full
A simple case: max size of queue is 1
24
Solution (sleep?)
 Sleep =
– “don’t run me until something happens”
 What about this?
Dequeue(){
lock();
if (queue empty) {
sleep();
}
take one item;
unlock();
}
Enqueue(){
lock();
insert item;
if (thread waiting)
wake up dequeuer();
unlock();
}
25
Another solution
 Does this work?
Dequeue(){
lock();
if (queue empty){
unlock();
sleep();
remove item;
}
else unlock;
}
Enqueue(){
lock();
insert item;
if (thread waiting)
wake up dequeuer();
unlock();
}
26
Conditional variables
 Make it possible/easy to go to sleep
– Atomically:
• release lock
• put thread on wait queue
• go to sleep
 Each cv has a queue of waiting threads
 Worry about threads that have been put on
the wait queue but have NOT gone to sleep
yet?
– no, because those two actions are atomic
 Each condition variable associated with one
lock
27
Conditional variables
 Wait for 1 event, atomically release lock
– wait(Lock& l, CV& c)
• If queue is empty, wait
– Atomically releases lock, goes to sleep
– You must be holding lock!
– May reacquire lock when awakened (pthreads do)
– signal(CV& c)
• Insert item in queue
– Wakes up one waiting thread, if any
– broadcast(CV& c)
• Wakes up all waiting threads
 Monitors = locks + condition variables
– Sometimes combined with data structures
Lets take a look at a demo
28
Producer-consumer problem using pthread conditionals
void * consumer (void *){
while (true) {
pthread_mutex_lock(&l);
while (q.empty()){
pthread_cond_wait(&nempty, &l);
}
cout << q.pop_back() << endl;
pthread_mutex_unlock(&l);
}
}
void * producer(void *){
while (true) {
pthread_mutex_lock(&l);
q.push_front (1);
pthread_cond_signal(&nempty);
pthread_mutex_unlock(&l);
}
}
29