posix synchronization introduction to operating systems: discussion module 5

35
POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Upload: laurence-hunter

Post on 13-Dec-2015

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

POSIX Synchronization

Introduction to Operating Systems: Discussion Module 5

Page 2: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

POSIX Synchronization

Synchronization objects are variables in memory that you access just like data.

Threads in different processes can communicate with each other through synchronization objects placed in shared memory. Threads in different processes are generally invisible to each

other.

The available types of synchronization objects include: Mutex Locks Condition Variables

Page 3: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Steps in using a mutex

Initialize an attribute object Reset attribute settings

Can the mutex be shared across processes? Is there any deadlock protection?

Create a mutex using the attribute object Use the mutex

Lock, unlock, trylock Destroy the mutex

Page 4: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Attribute Initialization

int pthread_mutexattr_init(

pthread_mutexattr_t *mattr); Use pthread_mutexattr_init() to initialize

attributes associated with this object to their default values. Storage for each attribute object is allocated by the threads system during execution.

The default value of the pshared attribute when this function is called is PTHREAD_PROCESS_PRIVATE, which means that the initialized mutex can only be used within a process.

Page 5: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Mutex scope

int pthread_mutexattr_setpshared( pthread_mutexattr_t *mattr, int pshared);

The scope of a mutex variable can be either process private (intraprocess) or system wide (interprocess).

If the mutex is created with the pshared attribute set to the PTHREAD_PROCESS_SHARED state, and it exists in shared memory, it can be shared among threads from more than one process.

pshared can take one of two values: PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_SHARED

Page 6: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Mutex Type

int pthread_mutexattr_settype( pthread_mutexattr_t *attr , int type); pthread_mutexattr_settype() sets the mutex

type attribute. The type argument specifies the type of mutex. Valid mutex types include: PTHREAD_MUTEX_NORMAL

This type of mutex does not detect deadlock. A thread attempting to relock this mutex without first unlocking it will

deadlock. Attempting to unlock a mutex locked by a different thread results in

undefined behavior. Attempting to unlock an unlocked mutex results in undefined behavior.

Page 7: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Mutex Type

PTHREAD_MUTEX_ERRORCHECK This type of mutex provides error checking. A thread attempting to relock this mutex without first unlocking

it will return with an error. A thread attempting to unlock a mutex which another thread has

locked will return with an error. A thread attempting to unlock an unlocked mutex will return with

an error.

Page 8: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Mutex Type

PTHREAD_MUTEX_RECURSIVE A thread attempting to relock this mutex without first unlocking

it will succeed in locking the mutex. The relocking deadlock which can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex.

Multiple locks of this mutex require the same number of unlocks to release the mutex before another thread can acquire the mutex.

A thread attempting to unlock a mutex which another thread has locked will return with an error.

A thread attempting to unlock an unlocked mutex will return with an error.

Page 9: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Mutex Type

PTHREAD_MUTEX_DEFAULT Attempting to recursively lock a mutex of this type results in

undefined behavior. Attempting to unlock a mutex of this type which was not locked

by the calling thread results in undefined behavior. Attempting to unlock a mutex of this type which is not locked

results in undefined behavior.

Page 10: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Attribute Destruction

int pthread_mutexattr_destroy(

pthread_mutexattr_t *mattr); Before a mutex attribute object can be reinitialized, it

must first be destroyed by a call to pthread_mutexattr_destroy().

If the object is not destroyed, a memory leak will result.

Page 11: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Initialize a Mutex

int pthread_mutex_init(

pthread_mutex_t *mp,

const pthread_mutexattr_t *mattr);

When the mutex is initialized, it is in an unlocked state A mutex lock must not be reinitialized or destroyed

while other threads might be using it. If a mutex is reinitialized or destroyed, the application

must be sure the mutex is not currently in use.

Page 12: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Lock a Mutex

int pthread_mutex_lock(

pthread_mutex_t *mutex);

Use pthread_mutex_lock() to lock the mutex pointed to by mutex.

When pthread_mutex_lock() returns, the mutex is locked and the calling thread is the owner.

If the mutex is already locked and owned by another thread, the calling thread blocks until the mutex becomes available.

Page 13: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Unlock a Mutex

int pthread_mutex_unlock( pthread_mutex_t *mutex);

Use pthread_mutex_unlock() to unlock the mutex pointed to by mutex

pthread_mutex_unlock() releases the mutex object referenced by mutex

If there are threads blocked on the mutex object referenced by mutex when pthread_mutex_unlock()is called, the scheduling policy is used to determine which thread shall acquire the mutex.

Page 14: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Lock with a Nonblocking Mutex

int pthread_mutex_trylock( pthread_mutex_t *mutex);

Use pthread_mutex_trylock( ) to attempt to lock the mutex pointed to by mutex

pthread_mutex_trylock()is a non-blocking version of pthread_mutex_lock()

If the mutex object referenced by mutex is currently locked (by any thread, including the current thread), the call returns immediately(EBUSY). Otherwise, the mutex is locked and the calling thread is the owner.

Page 15: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Destroy a Mutex

int pthread_mutex_destroy(

pthread_mutex_t *mutex); Use pthread_mutex_destroy( ) function

to destroy a previously initialized mutex The mutex can not be used after it has been

destroyed Note that the space for storing the mutex is not

freed

Page 16: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

mutex.c #include <pthread.h>

#include <unistd.h>

static pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;

static void *print_thread (void *param) { const char *name = param; int i; while (true) { pthread_mutex_lock(& print_lock); printf ("Hello "); printf ("from "); printf ("`%s' ", name); for (i = 'A'; i <= 'Z'; i++) printf ("%c", i); printf ("\r\n"); pthread_mutex_unlock(& print_lock); } return 0;}

Page 17: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

mutex.c (continued)int main (void) {

pthread_t id;pthread_create (&id, NULL, print_thread, "Thread 1");pthread_create (&id, NULL, print_thread, "Thread 2");pthread_create (&id, NULL, print_thread, "Thread 3");pthread_create (&id, NULL, print_thread, "Thread 4");pthread_create (&id, NULL, print_thread, "Thread 5");pthread_create (&id, NULL, print_thread, "Thread 6");

while (1) {pthread_mutex_lock(& print_lock);printf ("sleep\r\n");pthread_mutex_unlock(& print_lock);sleep (1);

}return 0;

}

Page 18: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Condition Variables

A condition variable is used to wait until a particular condition is true like in a monitor

Always use condition variables together with a mutex lock The mutex provides the mutual exclusive aspect of a

monitor The attributes for condition variables must be set

and initialized before the condition variables can be used

Page 19: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Steps in using a condition variable

Create an attribute object Create a condition variable, associating it with an

existing mutex Use the condition variable

Wait, signal, broadcast Destroy the condition variable

Page 20: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Attribute Initialization

int threads_condattr_init( pthread_condattr_t *cattr);

The pthread_condattr_init() call returns a pointer to an opaque object

The possible values of cattr’s scope are PTHREAD_PROCESS_PRIVATE (the default) and PTHREAD_PROCESS_SHARED

If the object is not destroyed, a memory leak will result

Page 21: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Setting The Scope

int pthread_condattr_setpshared( pthread_condattr_t *cattr, int pshared);

pthread_condattr_setpshared( ) sets the scope of a condition variable to either process private(intraprocess) or system wide (interprocess)

PTHREAD_PROCESS_SHARED it can be shared among threads from more than one process

PTHREAD_PROCESS_PRIVATE (default value): only those threads created by the same process can operate on the object

Page 22: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Attribute Destruction

int pthread_condattr_destroy(

pthread_condattr_t *cattr); Use pthread_condattr_destroy( ) to

remove storage and render the object invalid The object must be reinitialized before it can be

reused

Page 23: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Initialize A Condition Variable

int pthread_cond_init(

pthread_cond_t *cv,

const pthread_condattr_t *cattr); Initializes the condition variable pointed at by cv to

its default value (cattr is NULL), or to specify condition variable attributes that are already set with pthread_condattr_init().

Page 24: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Wait On Condition Variable

int pthread_cond_wait( pthread_cond_t *cv, pthread_mutex_t *mp); Use pthread_cond_wait( ) to release the

mutex pointed to by mp and to cause the calling thread to block on the condition variable pointed to by cv

The blocked thread can be awakened by a pthread_cond_signal(), or a pthread_cond_broadcast()

Page 25: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Wait on Condition Variable

Page 26: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Unblock A Thread

int pthread_cond_signal( pthread_cond_t *cv); Use pthread_cond_signal( ) to unblock

one thread that is blocked on the condition variable pointed to by cv.

If more than one thread is blocked on a condition variable, the scheduling policy determines the order in which blocked threads are awakened.

For SCHED_OTHER, threads are awakened in priority order.

Page 27: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Condition Signal

BEEP

Page 28: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Unblock All Threads

Int pthread_cond_broadcast(

pthread_cond_t *cv); Use pthread_cond_broadcast( ) to unblock all

threads that are blocked on the condition variable pointed to by cv, specified by pthread_cond_wait().

When no threads are blocked on the condition variable, pthread_cond_broadcast() has no effect.

Page 29: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Condition Broadcast

SQUEAL

Page 30: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Destroy Condition Variable

int pthread_cond_destroy(

pthread_cond_t *cv); The pthread_cond_destroy() function

destroys a previously initialized condition variable The condition variable must not be used after it has

been destroyed. The space for storing the condition variable is not

freed.

Page 31: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

condvar.c#include <pthread.h> #include <stdio.h> #define MAX 1000 #define MAX_COUNT 2000

int count = 0;pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t count_max = PTHREAD_COND_INITIALIZER; int thread_id[3] = {0,1,2};

void increment(void *); void watch(void *);

Page 32: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

condvar.c

int main(int argc, char *argv[]) { int i; pthread_t thread[3]; pthread_create(&thread[0], NULL, increment, (void*)&thread_id[0]); pthread_create(&thread[1], NULL, increment, (void*)&thread_id[1]); pthread_create(&thread[2], NULL, watch, (void*)&thread_id[2]);

for(i=0; i< 3 ; i++) pthread_join(thread[i], NULL); return 0;}

Page 33: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

condvar.c (continued)void watch(void* ID) { int* id = (int*)ID; pthread_mutex_lock(&count_mutex); while(count <= MAX_COUNT) { pthread_cond_wait(&count_max, &count_mutex); printf("Inside the watch() and the value is %d\n", count); } pthread_mutex_unlock(&count_mutex); }

Page 34: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

condvar.c (continued)

void increment(void* ID) { int *id = (int*)ID; int i; for(i=0; i< MAX ; i++) { pthread_mutex_lock(&count_mutex); count++; printf("in increment counter by threadof id :%d, and count :%d\n",*id, count); pthread_cond_signal(&count_max); pthread_mutex_unlock(&count_mutex); } }

Page 35: POSIX Synchronization Introduction to Operating Systems: Discussion Module 5

Compiling your C++ code with pthreads

You should use the g++ form of complier invocation

You must link with the pthread library g++ mycode.cpp -lpthread

Use cc or gcc to compile c code If you don’t include the link option, only your main

thread will execute! This works with Solaris; details vary from system

to system.