2/28/2019
Review: Definition of Monitor
• Semaphores are confusing because dual purpose:
– Both mutual exclusion and scheduling constraints
– Cleaner idea: Use locks for mutual exclusion and
condition variables for scheduling constraints
• Monitor: a lock and zero or more condition variables
Pthread Programming for managing concurrent access to shared data
– Use of Monitors is a programming paradigm
• Lock: provides mutual exclusion to shared data:
– Always acquire before accessing shared data structure
– Always release after finishing with shared data
• Condition Variable: a queue of threads waiting for
something inside a critical section
– Key idea: allow sleeping inside critical section by
atomically releasing lock at time we go to sleep
1 – Contrast to semaphores: Can’t wait inside critical section
1 2
Programming with Monitors
• Monitors represent the logic of the program What are Pthreads?
– Wait if necessary
– Signal when change something so any waiting • Historically, hardware vendors have
threads can proceed implemented their own proprietary versions of
• Basic structure of monitor-based program: threads. Not portable.
lock
while (need to wait) { Check and/or update • Pthread is a standardized thread programming
condvar.wait(); state variables
} Wait if necessary interface specified by the IEEE POSIX (portable
unlock operating systems interface) in 1995.
do something so no need to wait
• Pthreads are defined as a set of C language
lock programming types and procedure calls,
condvar.signal(); Check and/or update implemented with a pthread.h header/include
state variables
unlock
file and a thread library.
4
3 4
Why Pthread ? Why Pthread ?
• To realize potential program performance gains. • Threaded applications offer potential
• When compared to the cost of creating and performance gains and practical advantages
over non-threaded applications in several other
managing a process, a thread can be created ways:
with much less operating system overhead. – Overlapping CPU work with I/O
Managing threads requires fewer system – Priority/real-time scheduling: tasks which are more
resources than managing processes. important can be scheduled to supersede or interrupt
lower priority tasks.
• All threads within a process share the same
– Asynchronous event handling: tasks which service
address space. Inter-thread communication is events of indeterminate frequency and duration can
more efficient and in many cases, easier to use be interleaved. For example, a web server can both
than inter-process communication. transfer data from previous requests and manage the
arrival of new requests.
5 6
5 6
1
2/28/2019
Include files and libraries The Pthreads API
• .h file • Thread management: The first class of
functions work directly on threads - creating,
#include <pthread.h> terminating, joining, etc.
#include <semaphore.h> //for semaphore only • Semaphores: provide for create, destroy, wait,
and post on semaphores.
• Mutexes: provide for creating, destroying,
• Compile and Linking locking and unlocking mutexes.
• Condition variables: include functions to
$gcc foo.c -o foo -lpthread –lrt create, destroy, wait and signal based upon
(for semaphore) specified variable values.
7 8
7 8
Thread Creation Thread Termination and Join
pthread_create (tid, attr, start_routine, arg) pthread_exit (value) ;
• It returns the new thread ID via the tid argument. • This Function is used by a thread to terminate. The
• The attr parameter is used to set thread return value is passed as a pointer.
attributes, NULL for the default values.
pthread_join (tid, value_ptr);
• The start_routine is the C routine that the thread
will execute once it is created. • The pthread_join() subroutine blocks the calling thread
until the specified threadid thread terminates.
• A single argument may be passed to • Return 0 on success, and negative on failure. The
start_routine via arg. It must be passed by returned value is a pointer returned by reference. If you
reference as a pointer cast of type void. do not care about the return value, you can pass NULL
for the second argument.
9 10
9 10
Example Code - Pthread Creation and Termination
#include <pthread.h> Thread functions
#include <stdio.h>
void *PrintHello(void * id) sched_yield();
{ pthread_self ();
printf(“Thread%d: Hello World!\n", id); pthread_equal (tid1,tid2);
pthread_exit(NULL);
} • sched_yield() suspends the execution of the
current thread. This allows another thread
int main (int argc, char *argv[]) immediate access.
{ • The pthread_self() routine returns the
pthread_t thread0, thread1; unique, system assigned thread ID of the
pthread_create(&thread0, NULL, PrintHello, (void *) 0); calling thread.
pthread_create(&thread1, NULL, PrintHello, (void *) 1);
pthread_exit(NULL); • The pthread_equal() routine compares two
} thread IDs. If the two IDs are different 0 is
returned, otherwise a non-zero value is
returned.
11 12
11 12
2
2/28/2019
Mutex Variables Creating / Destroying Mutexes
• For thread synchronization and protecting pthread_mutex_init (mutex, attr)
shared data when multiple writes occur.
• A mutex variable acts like a "lock" protecting
pthread_mutex_destroy (mutex)
access to a shared data resource. • Mutex variables must be declared with
• Only one thread can lock (or own) a mutex type pthread_mutex_t, and must be
variable at any given time. Thus, even if several initialized before they can be used.
threads try to lock a mutex only one thread will
be successful. No other thread can own that • attr, mutex object attributes, specified as
mutex until the owning thread unlocks that NULL to accept defaults
mutex. Threads must "take turns" accessing
protected data.
13 14
13 14
Locking / Unlocking Mutexes Semaphores
pthread_mutex_lock (mutex); • Semaphore are not defined in the
pthread_mutex_trylock (mutex); POSIX.4a (pthread) specifications, but
pthread_mutex_unlock (mutex);
they are included in the POSIX.4 (realtime
• The pthread_mutex_lock() routine is used by a thread to
acquire a lock on the specified mutex variable. The extension) specifications.
thread blocks if the mutex is already locked by another • .h
thread.
• pthread_mutex_trylock() will attempt to lock a mutex. #include <semaphore.h>
However, if the mutex is already locked, the routine will • Semaphore descriptors are declared
return immediately with a "busy" error code.
global
• pthread_mutex_unlock() will unlock a mutex if called by
the owning thread. ex: sem_t mutex, full, empty;
15 16
15 16
Routines of Semaphore Condition Variables
sem_t sp; • While mutexes implement synchronization by controlling
thread access to data, condition variables allow threads
• sem_init(&sp, pshared, init_value) to synchronize based upon the actual value of data.
• Without condition variables, the programmer would need
– If pshared is nonzero, the semaphore can be to have threads continually polling (possibly in a critical
shared between processes. section), to check if the condition is met. This can be
very resource consuming since the thread would be
• sem_destroy(&sp) continuously busy in this activity. A condition variable is
• sem_wait (&sp); //P operation, wait a way to achieve the same goal without polling.
• A condition variable is always used in conjunction with a
• sem_trywait(&sp); mutex lock.
• sem_post (&sp); // V operation, signal
17 18
17 18
3
2/28/2019
A representative sequence for using condition variables
Conditional Variable Routines Main Thread
•Declare and initialize global data/variables
•Declare and initialize a condition variable object
•Declare and initialize an associated mutex
• pthread_cond_init (condition, attr) •Create threads A and B to do work
Thread A Thread B
• pthread_cond_destroy (condition) •Do work up to the point where a certain
condition must occur (such as "count" must
•Do work
•Lock associated mutex
• pthread_cond_wait (condition, mutex) reach a specified value)
•Lock associated mutex and check value of a
•Change the value of the global
variable that Thread-A is waiting
global variable upon.
• pthread_cond_signal (condition) •Call pthread_cond_wait() to perform a •Check value of the global
blocking wait for signal from Thread-B. It will Thread-A wait variable. If it fulfills
• pthread_cond_broadcast (condition) automatically and atomically unlocks the the desired condition, signal
associated mutex variable so that it can be Thread-A.
used by Thread-B. •Unlock mutex.
•When signalled, wake up. Mutex is •Continue
automatically and atomically locked.
•Explicitly unlock mutex.
•Continue
19 Main Thread Join / Continue 20
19 20
References
• pthread libraries
https://www.cs.cmu.edu/afs/cs/academic/class/1
5492-f07/www/pthreads.html
• POSIX thread programming
http://www.llnl.gov/computing/tutorials/pthreads/
• "Multithreaded, Parallel, and Distributed
Programming" by Gregory R. Andrews
21
21