[go: up one dir, main page]

0% found this document useful (0 votes)
17 views6 pages

ANP - 2. Synchronization in Multithreaded Programs

The document discusses mutexes and condition variables in threaded programming, emphasizing their role in ensuring mutual exclusion and synchronization among threads. It details the characteristics of mutexes, including atomicity, singularity, and non-busy wait, along with various mutex operations such as lock, unlock, and try-lock. Additionally, it provides examples of the producer-consumer problem to illustrate the practical application of mutexes and condition variables for managing shared resources in concurrent programming.
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)
17 views6 pages

ANP - 2. Synchronization in Multithreaded Programs

The document discusses mutexes and condition variables in threaded programming, emphasizing their role in ensuring mutual exclusion and synchronization among threads. It details the characteristics of mutexes, including atomicity, singularity, and non-busy wait, along with various mutex operations such as lock, unlock, and try-lock. Additionally, it provides examples of the producer-consumer problem to illustrate the practical application of mutexes and condition variables for managing shared resources in concurrent programming.
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/ 6

7/21/2017

Mutexes
• Threaded programs need to share data between
programs.
Thread Synchronization • Memory accesses to the same data are “mutually
exclusive.” (To avoid inconsistent state of data)
• Mutex provides direct programming support to
Harshad B. Prajapati handle mutual exclusive access.
Associate Professor
• Using mutex, a thread locks before entering critical
Information Technology Department,
section, and then the thread unlocks after exiting
Dharmsinh Desai University, Nadiad
from critical section.

Mutex characteristics Mutexes


• Mutex lock guarantees three things: • Mutex operation while three threads are
1. Atomicity - Locking a mutex is an atomic operation working simultaneously.
(no other thread succeeded in locking this mutex at
the same time)
2. Singularity - If a thread managed to lock a mutex, it is
assured that no other thread will be able to lock the
thread until the original thread releases the lock.
3. Non-Busy Wait – Other threads which could not
succeed in locking, will not consume any CPU
resource (i.e. no busy waiting).

Mutex: data types and functions Mutex: data types and functions
• Mutex: Create operation
• Mutex lock variable – int pthread_mutex_init(pthread_mutex_t *mutex,
pthread_mutexattr_t *attr);
–pthread_mutex_t mutex= • The pthread_mutex_init() function initializes the mutex referenced by
PTHREAD_MUTEX_INITIALIZER; mutex with attributes specified by attr.
• If attr is NULL, the default mutex attributes are used;
• This is a way of initializing mutex (lock) • Mutex: destroy operation
variable. – int pthread_mutex_destroy(pthread_mutex_t *mutex);
– The pthread_mutex_destroy() function destroys the mutex object
• The PTHREAD_MUTEX_INITIALIZER is a referenced by mutex;
constant defined in header file.
• Note: Generally, all functions return 0 on success and
error code on failure.

1
7/21/2017

Mutex: data types and functions Mutex: data types and functions
• Mutex: lock operation • Mutex: unlock operation
– int pthread_mutex_lock(pthread_mutex_t *mutex); – int pthread_mutex_unlock(pthread_mutex_t *mutex);
• The mutex object referenced by mutex is locked by calling pthread_mutex_lock(). • The pthread_mutex_unlock() function releases the mutex object referenced by
• If the mutex is already locked, the calling thread blocks until the mutex becomes mutex.
available.
• This operation returns with the mutex object referenced by mutex in the locked
state with the calling thread as its owner.

• Mutex: try-lock operation


– int pthread_mutex_trylock(pthread_mutex_t *mutex);
• It is identical to pthread_mutex_lock() except that if the mutex
object referenced by mutex is currently locked (by any thread,
including the current thread), the call returns immediately. (No
waiting)

Example: Producer-Consumer Example: Producer-Consumer


Problem Problem
#include <stdio.h> void* producer(void*); //producer thread function
#include <pthread.h> void* consumer(void*); //consumer thread function
#define MAXNITEMS 1000000 int min(int,int);
#define MAXNTHREADS 100
int main(int argc,char** argv){
int nitems; int i,nthreads,count[MAXNTHREADS];
struct{ pthread_t tid_produce[MAXNTHREADS],tid_consume;
pthread_mutex_t mutex;// mutex variable works as lock if(argc!=3){
int buff[MAXNITEMS];// shared buffer fprintf(stderr,"Usage : %s #items #threads\n",argv[0]);
int nput; //put pointer to shared buffer exit(-1);
int nval; //value to be put on shared buffer on nput index }
}shared={PTHREAD_MUTEX_INITIALIZER};

Example: Producer-Consumer Example: Producer-Consumer


Problem Problem
nitems=min(atoi(argv[1]),MAXNITEMS); /* start, then wait for consumer thread */
nthreads=min(atoi(argv[2]),MAXNTHREADS); pthread_create(&tid_consume,NULL,consumer,NULL);
/* start all producer threads */ pthread_join(tid_consume,NULL);
for(i=0;i<nthreads;i++){ exit(0);
count[i]=0; }
pthread_create(&tid_produce[i],NULL,producer,&count[i]);
}
/* wait for all producer threads */
for(i=0;i<nthreads;i++){
pthread_join(tid_produce[i],NULL);
printf("count[%d] = %d\n",i,count[i]);
}

2
7/21/2017

Example: Producer-Consumer Example: Producer-Consumer


Problem Problem
void* consumer(void* arg){ void * producer(void* arg){
int i=0; for(;;){
printf("-------CONSUMER STARTS--------\n"); // pthread_mutex_lock(&shared.mutex);
if(shared.nput>=nitems){
for(i=0;i<nitems;i++){ // pthread_mutex_unlock(&shared.mutex);
if(shared.buff[i]!=i) return NULL;
// if consumer finds any wrong value in buffer, just print it }
printf("buff[%d]=%d\n",i,shared.buff[i]); shared.buff[shared.nput]=shared.nval;
} shared.nput++;
printf("-------CONSUMER ENDS--------\n"); shared.nval++;
return NULL; // pthread_mutex_unlock(&shared.mutex);
} *((int*)arg)+=1;
}
}

Example: Producer-Consumer
Condition Variables
Problem
int min(int a,int b){ • Consider a situation
if(a<b)
– If a thread does not want to do any activity (wait) until it
return a;
gets some resources(or some state of resources); And
else
when this happens, the thread wants to get informed
return b;
(notify).
}
– The solution is “using condition variable”.

Condition Variables: mutex v/s


Condition Variables
condition variable
• A mutex • A condition variable is of type
– It provides mutual exclusion.
– It provides mutual exclusive (controlled) access to shared
– pthread_cond_t
data • Ex: pthread_cond_t
condv=PTHREAD_COND_INITIALIZER;
• while condition variable
– It allows threads to synchronize based upon the actual
value of data. – to initialize it during runtime, one must use the
– It provides a signaling mechanism. pthread_cond_init() function. (See man pages)
– Without condition variable, the threads need to
continuously wait for some condition. (It is called polling,
busy waiting, and it wastes CPU time)

3
7/21/2017

Condition Variables Condition Variables


• Functions • Functions
– int pthread_cond_wait(pthread_cond_t *cvptr, – int pthread_cond_timedwait(pthread_cond_t
pthread_mutex_t *mptr); *cond, pthread_mutex_t *mutex, const struct
• block on a condition variable timespec *abstime);
• It is called with mutex locked by the calling thread (or • It allows the programmer to specify a timeout for the
undefined behaviour will result.) waiting, after which the function always returns, with a
• It automatically and atomically does following proper error value.
– Unlocks (releases) mutex
– causes the calling thread to block on the condition variable
cond
• When, pthread_cond_wait returns, it locks the mutex.

Condition Variables Condition Variables


struct timeval tv; • int pthread_cond_signal(pthread_cond_t *
struct timespec ts; cptr);
If(gettimeofday(&tv,NULL)<0){
– This call unblocks at least one of the threads that
//error
are blocked on the specified condition variable
}
cond (if any threads are blocked on cond).
ts.tv_sec=tv.tv_sec+5; /* 5 seconds in future */
ts.tv_nsec=tv.tv_usec * 1000; /* micro to nano sec*/
– When a thread is signalled (wake up), mutex is
automatically and atomically locked.
pthread_cond_timedwait(…,&ts); • int pthread_cond_broadcast(pthread_cond_t
*cond);
– The call unblocks all threads currently blocked on
the specified condition variable cond.

Condition variable for synchronization


Condition Variables
(General structure of program)
• int pthread_cond_destroy(pthread_cond_t //part of a thread that wakes-up sleeping thread
*cond); struct{
– It destroies the given condition variable specified pthread_mutex_t mutex;
by cond (It frees any system resources it might be pthread_cond_t cond;
using.) variable_maintaing_condition_value
}var=//initialization code{…};
pthread_mutex_lock(&var.mutex);
Set condition true
pthread_cond_signal(&var.cond);
ptherad_mutex_unlock(&var.mutex);

4
7/21/2017

Condition variable for synchronization


Program
(General structure of program)
//part of a thread that sleeps until specified condition • proConMutexWCondV.c
occurs #include <stdio.h>
#include <pthread.h>
#define MAXNITEMS 1000000
pthread_mutex_lock(&var.mutex);
#define MAXNTHREADS 100
while(condition_is_false)
pthread_cond_wait(&var.cond); int nitems;
Modify condition int buff[MAXNITEMS];// shared buffer
ptherad_mutex_unlock(&var.mutex);

Program Program
/* mutex for synchronized access to buffer*/ void* producer(void*); //producer thread function
struct{ void* consumer(void*); //consumer thread function
pthread_mutex_t mutex;// mutex variable works as lock
int min(int,int);
int nput; //put pointer to shared buffer
int nval; //value to be put on shared buffer on nput index int main(int argc,char** argv){
}shared={PTHREAD_MUTEX_INITIALIZER}; int i,nthreads,count[MAXNTHREADS];
pthread_t tid_produce[MAXNTHREADS],tid_consume;
/* mutex for synchronized access to nready*/ if(argc!=3){
struct {
fprintf(stderr,"Usage : %s #items #threads\n",argv[0]);
pthread_mutex_t mutex;
pthread_cond_t cond; exit(-1);
int nready; }
}ready={PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER}; nitems=min(atoi(argv[1]),MAXNITEMS);
nthreads=min(atoi(argv[2]),MAXNTHREADS);

Program Program
/* Create all producer threads */ /* wait for all producer threads and cosumer thread */
for(i=0;i<nthreads;i++){ for(i=0;i<nthreads;i++){
count[i]=0; pthread_join(tid_produce[i],NULL);
printf("count[%d] = %d\n",i,count[i]);
pthread_create(&tid_produce[i],NULL,producer,&count[i }
]); pthread_join(tid_consume,NULL);
} exit(0);
/* Create one consumer thread */ }
pthread_create(&tid_consume,NULL,consumer,NULL);

5
7/21/2017

Program Program
void* consumer(void* arg){ if(buff[i]!=i)
int i=0; // if consumer finds any wrong value in buffer, just print it
for(i=0;i<nitems;i++){ printf("buff[%d]=%d\n",i,buff[i]);
pthread_mutex_lock(&ready.mutex); }
// go to sleep, if no new produced item is ready return NULL;
while(ready.nready==0) }
pthread_cond_wait(&ready.cond,&ready.mutex);
ready.nready--;
pthread_mutex_unlock(&ready.mutex);

Program Program
void * producer(void* arg){ pthread_mutex_lock(&ready.mutex);
for(;;){ //producer produced an item, awakens thread that are waiting
pthread_mutex_lock(&shared.mutex); for non-zero value of ready.nready
if(shared.nput>=nitems){ if(ready.nready==0)
pthread_mutex_unlock(&shared.mutex); pthread_cond_signal(&ready.cond);
return NULL; ready.nready++;
} pthread_mutex_unlock(&ready.mutex);
buff[shared.nput]=shared.nval; *((int*)arg)+=1;
shared.nput++; }
shared.nval++; }
pthread_mutex_unlock(&shared.mutex);

Program
int min(int a,int b){
if(a<b)
return a;
else
return b;
}

You might also like