Quiz on pthread basics

Pthreads Basics Quiz body {margin: 10px;} Pthreads Basics QuizA quiz on basics of pthreads 1. Which header file needs to be used for pthread programming ?
pthreads.h
pthread.h
p_thread.h
posix.h

Pthreads are not useful in uniprocessor systems
False
True
Depends on the compiler
Depends on the processor

What are the flags that are passed while compiling a pthread program using gcc
-pthread
-lpthread
-gccpthread
-thread

Among the arguments passed to pthread API pthread_create the final argument, is.
Attributes of the thread
Name of the thread
Data being passed to the thread
Thread id

The data type used for storing the thread id is
pthread
pthread_t
p_thread_t
pthread_id

Which of the following APIs can be used for synchronization between threads
pthread_exit
pthread_cancel
pthread_self
pthread_join

To create a detachable thread which of the following structures needs to be modified
pthread_attr_t
pthread_t
pthread_attribute
attribute_t

pthread_self returns
The thread id
The thread attribute
Thread data
Thread running time

Two threads can be compared using the API
compare_pthreads
pthread_equal
pthread_compare
equal_pthread

pthread_create(&threads_id, NULL, Hello_world, NULL); creates a thread
Called Hello_world with default attributes
Called Hello_world with all attributes set to NULL
Called Hello with default attributes
Called Hello with all attributes set to NULL

Answers the quiz are available at : Answers to pthreads basic quiz

Category: Linux | Comments Off on Quiz on pthread basics

using read write lock in pthreads

When sharing resources between multiple threads, it is safe to allow multiple readers to access the resource simultaneous as they would not alter any data but only one writer should be allowed to access the resource at any given time.

The standard mutex, pthread_mutex_t, allows only one process to access the resource irrespective of whether the process is a reader or writer. The behavior even though safe, is not efficient, as the readers are made to wait even though they are not going to modify the data.

To allow multiple readers to access a resource at the same time we can use pthread_rwlock_t in pthreads. The pthread_rwlock_t which is a read,write lock allows multiple readers to access the resource, but allows only one reader at any given time.

The initialization function for this s

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr); Where rwlock is the locking variable of the type pthread_rwlock_t attr is the attributes of the lock, which can be set to NULL for default attributes.

Thus we can use the initialization function as

pthread_rwloc_t rwlock; pthread_rwlock_init(rwlock,NULL);

Once the lock is initialized we can lock a resource for writing using the function

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

Once the write lock is held no other process can access the resource until it is unlocked using

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

To lock the resource only for reading and not writing we can use the function

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

Once the lock is held for reading, any number of other processes can access the resource of reading by locking the resource simultaneously. But the lock can not be held for writing, if it is already being held for reading. The lock can be unlocked using

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

To depict the working of rwlock let us look at the following example in which we create 4 threads, two for writing write_1,write_2, and two for reading,read_1,read_2.

We try to lock the rwlock in the following order

write_1->write_2->read_1->read_2

According to the above order we should not be able to get lock in write_1 and write_2 simultaneously but we should be able to get the lock simultaneously for read_1 and read_2.

#include #include #include pthread_rwlock_t rwlock; void * write(void *temp) { char *ret; FILE *file1; char *str; ret=pthread_rwlock_wrlock(&rwlock); printf(“\nFile locked, please enter the message \n”); str=(char *)malloc(10*sizeof(char)); file1=fopen(“temp”,”w”); scanf(“%s”,str); fprintf(file1,”%s”,str); fclose(file1); pthread_rwlock_unlock(&rwlock); printf(“\nUnlocked the file you can read it now \n”); return ret; } void * write_2(void *temp) { char *ret; FILE *file1; char *str; sleep(3); ret=pthread_rwlock_wrlock(&rwlock); printf(“\nFile locked, please enter the message \n”); str=(char *)malloc(10*sizeof(char)); file1=fopen(“temp”,”a”); scanf(“%s”,str); fprintf(file1,”%s”,str); fclose(file1); pthread_rwlock_unlock(&rwlock); printf(“\nUnlocked the file you can read it now \n”); return ret; } void * read_1(void *temp) { char *ret; FILE *file1; char *str; sleep(5); pthread_rwlock_rdlock(&rwlock); printf(“\n1 Opening file for reading\n”); file1=fopen(“temp”,”r”); str=(char *)malloc(10*sizeof(char)); fscanf(file1,”%s”,str); printf(“\nMessage from file is %s \n”,str); sleep(3); fclose(file1); printf(“\nUnlocking rwlock\n”); pthread_rwlock_unlock(&rwlock); return ret; } void * read_2(void *temp) { char *ret; FILE *file1; char *str; sleep(6); pthread_rwlock_rdlock(&rwlock); printf(“\n2 Opening file for reading\n”); file1=fopen(“temp”,”r”); str=(char *)malloc(10*sizeof(char)); fscanf(file1,”%s”,str); printf(“\nMessage from file is %s \n”,str); fclose(file1); pthread_rwlock_rdlock(&rwlock); return ret; } main() { pthread_t thread_id,thread_id1,thread_id3,thread_id4; pthread_attr_t attr; int ret; void *res; pthread_rwlock_init(&rwlock,NULL); ret=pthread_create(&thread_id,NULL,&write,NULL); ret=pthread_create(&thread_id1,NULL,&read_1,NULL); ret=pthread_create(&thread_id3,NULL,&read_2,NULL); ret=pthread_create(&thread_id4,NULL,&write_2,NULL); printf(“\n Created thread”); pthread_join(thread_id,&res); pthread_join(thread_id1,&res); pthread_join(thread_id3,&res); pthread_join(thread_id4,&res); pthread_rwlock_destroy(&rwlock); }

Save the above code as rw_lock.c

Compile it using the -lpthread flag

$ cc -lpthread rw_lock.c -o rw_lock $ ./rw_lock Created thread File locked, please enter the message Hello Unlocked the file you can read it now File locked, please enter the message World Unlocked the file you can read it now 1 Opening file for reading Message from file is HelloWorld 2 Opening file for reading Message from file is HelloWorld Unlocking rwlock

From the output we can see that the two writes were executed one after the other. But in case of reads, even though read_1 had not unlocked the rwlock, read_2 was allowed into the critical section and read the file. Thus indicating that multiple readers are allowed but only one writer is allowed into the critical section.

Category: Linux | Comments Off on using read write lock in pthreads

using pthread_mutex_timedlock in linux.

We saw in the post ” ” how we can use mutexes in pthreads to achieve synchronization among various threads. Along with the the three functions we saw, there is a fourth mutex function that we can use when we want to wait on a mutex for only a specific duration and then continue irrespective of whether we are able to get a lock on the mutex or not. The function for timed operation on mutex it pthread_mutex_timedlock whose syntax is

int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict abs_timeout);

The timeout is the time for which we want to wait on the mutex. To specify the timeout we need to use the structure timepsec which has two fields one for seconds and other for nanoseconds as shown below.

struct timespec { __time_t tv_sec; /* Seconds. */ long int tv_nsec; /* Nanoseconds. */ };

The mutex if available will be locked immediately, if the mutex is not available the thread will wait for the duration of time mentioned in the abs_timeout and then exit from the wait.

The following program shows an example of using the pthread_mutex_timedlock. In the program thread1 takes a value as input from the user and assigns it to a variable “temp”. In thread2 the same variable is accessed and its value is printed. Thread1 locks a mutex while getting the value for temp from the user, but thread2 waits only for 5 seconds for the mutex to get unlocked after which it exits with a time out message and does not print the value of the variable temp.

To mention the timeout we need to first allocate memory for a timespec structure

struct timespec *wait wait=(struct timespec *)(malloc(sizeof(struct timespec)); wait->tv_sec=5; wait->tv_nsec=0;

Thus now we have a timespec structure with 5 seconds and 0 nanoseconds as the time values, which can be passed to the function pthread_mutex_timedlock to achieve a 5 second timeout.
The whole function looks as follows

#include#include#include#include pthread_mutex_t mutex1,mutex2; #define perror(s) printf(“\n” s “\n”); int temp; void * func1(){ pthread_mutex_lock(&mutex1); printf(“\nEnter a value for temp\n”); scanf(“%d”,&temp); pthread_mutex_unlock(&mutex1); } void * func2() { struct timespec *wait; int ret; wait=(struct timespec *)(malloc(sizeof(struct timespec))); wait->tv_sec=5; wait->tv_nsec=0; sleep(5); ret=pthread_mutex_timedlock(&mutex1,wait); if(ret!=0){ perror(“Wait timed out”); return ; } printf(“\nvalue assigned for temp is %d\n”,temp); pthread_mutex_unlock(&mutex1); } main() { int ret; pthread_t thread1,thread2; ret=pthread_create(&thread1,NULL,&func1,NULL); if(ret!=0){ perror(“Unable to create thread”); } ret=pthread_create(&thread2,NULL,&func2,NULL); if(ret!=0){ perror(“Unable to create thread”); } printf(“Created threads”); pthread_join(thread1,NULL); pthread_join(thread2,NULL); }

Save the program as mutex_timedlock.c, and compile it with the flag -lpthread

$ cc -lpthread -o mutex_timedloc mutex_timedlock.c

While executing the program when the prompt for entering a value for the variable appears, if you wait for more than 5 seonds for entering the value, you will noticed the timed out message from the second thread will appear on the other hand if we enter the value with in 5 seconds the value entered is printed by the second thread. case1: Waiting for more than 5 seconds before entering the value

$ ./mutex_timedlock Created threads Enter a value for temp Wait timed out 5

Created threads Enter a value for temp 5 value assigned for temp is 5

Thus we are able to achieve a mutex lock for a specific duration using the pthread_mutex_timedlock function.

Category: Linux | Comments Off on using pthread_mutex_timedlock in linux.

ussing barriers in pthreads

pthreads allows us to create and manage threads in a program. When multiple threads are working together, it might be required that the threads wait for each other at a certain event or point in the program before proceeding ahead.

Let us say we have four threads, each of which is going to initialize a global variable. The 4 variables in turn might be used by all the four threads. Thus it would be feasible that all the threads wait for each other to finish the initialization of the variables before proceeding.

Such operations can be implemented by adding a barrier in the thread. A barrier is a point where the thread is going to wait for other threads and will proceed further only when predefined number of threads reach the same barrier in their respective programs.

To use a barrier we need to use variables of the type pthread_barrier_t. A barrier can be initialized using the function pthread_barrier_init, whose syntax is

int pthread_barrier_init(pthread_barrier_t *restrict barrier,const pthread_barrierattr_t *restrict attr, unsigned count); Arguments: barrier: The variable used for the barrier attr: Attributes for the barrier, which can be set to NULL to use default attributes count: Number of threads which must wait call pthread_barrier_wait on this barrier before the threads can proceed further.

Once a barrier in initialized, a thread can be made to wait on the barrier for other threads using the function pthread_barrier_wait whose syntax is

int pthread_barrier_wait(pthread_barrier_t *barrier);

Where the barrier is the same variable initialized using pthread_barrier_init.

A thread will keep waiting till the “count” number of threads passed during init do not call the wait function on the same barrier.

In the example below, we create 4 threads, and each thread assigns a value to one of he global variables and then later all the threads print the value of all the four variables. Thus to be able to print the value of all the variables the threads have to wait until all threads have not finished assigning the values. Thus we can make use of barriers to make the threads wait.

The init function :

pthread_barrier_init(&our_barrier,NULL,4);

initializes the barrier “our_barrier” to wait for four threads.

Thus till all the four threads have not called the pthread_barrier_wait the other threads will continue to wait.

Once pthread_barrier_wait has been called by 4 threads, all the threads will continue their execution of program.

A barrier can be destroyed using the function pthread_barrier_destroy, whose syntax is :

int pthread_barrier_destroy(pthread_barrier_t *barrier);

But note that the barrier should be destroyed only when no thread is executing a wait on the barrier.

#include #include #include int t1,t2,t3,t4; pthread_barrier_t our_barrier; void *thread1() { sleep(2); printf(“Enter value for t1: “); scanf(“%d”,&t1); pthread_barrier_wait(&our_barrier); printf(“\nvalues entered by the threads are %d %d %d %d \n”,t1,t2,t3,t4); } void *thread2() { sleep(4); printf(“Enter value for t2: “); scanf(“%d”,&t2); pthread_barrier_wait(&our_barrier); printf(“\nvalues entered by the threads are %d %d %d %d \n”,t1,t2,t3,t4); } void *thread3() { sleep(6); printf(“Enter value for t3: “); scanf(“%d”,&t3); pthread_barrier_wait(&our_barrier); printf(“\nvalues entered by the threads are %d %d %d %d \n”,t1,t2,t3,t4); } void *thread4() { int temp; sleep(8); printf(“Enter value for t4: “); scanf(“%d”,&t4); pthread_barrier_wait(&our_barrier); printf(“\nvalues entered by the threads are %d %d %d %d \n”,t1,t2,t3,t4); } main() { pthread_t thread_id_1,thread_id_2,thread_id_3,thread_id_4; pthread_attr_t attr; int ret; void *res; pthread_barrier_init(&our_barrier,NULL,4); ret=pthread_create(&thread_id_1,NULL,&thread1,NULL); if(ret!=0) { printf(“Unable to create thread1”); } ret=pthread_create(&thread_id_2,NULL,&thread2,NULL); if(ret!=0) { printf(“Unable to create thread2”); } ret=pthread_create(&thread_id_3,NULL,&thread3,NULL); if(ret!=0) { printf(“Unable to create thread3”); } ret=pthread_create(&thread_id_4,NULL,&thread4,NULL); if(ret!=0) { printf(“Unable to create thread4”); } printf(“\n Created threads \n”); pthread_join(thread_id_1,NULL); pthread_join(thread_id_2,NULL); pthread_join(thread_id_3,NULL); pthread_join(thread_id_4,NULL); pthread_barrier_destroy(&our_barrier); }

Save the program as pthread_barrier.c and compile it by passing the -lpthread flag.

$ cc -lpthread -o pthread_barrier pthread_barrier.c $ ./pthread_barrier Enter value for t1: 10 Enter value for t2: 20 Enter value for t3: 30 Enter value for t4: 40 values entered by the threads are 10 20 30 40 values entered by the threads are 10 20 30 40 values entered by the threads are 10 20 30 40 values entered by the threads are 10 20 30 40

To stress on usefulness of the barrier, we can change barrier initialization in the above code to wait for only 3 threads i.e.

pthread_barrier_init(&our_barrier,NULL,3);
And remove the pthread_barrier_wait from the the 4th thread.

After the above changes, if we compile and execute the code the output would be

Created threads Enter value for t1: 10 Enter value for t2: 20 Enter value for t3: 30 values entered by the threads are 10 20 30 0 values entered by the threads are 10 20 30 0 values entered by the threads are 10 20 30 0 Enter value for t4: 40 values entered by the threads are 10 20 30 40

The first three threads could not get the value entered by the fourth thread as they moved over the barrier as soon as three threads executed the wait function.

Category: Linux | Comments Off on ussing barriers in pthreads

Using condition variables in pthreads

Along with mutexes, pthreads gives us another tool for synchronization between the threads, condition variables. Condition variables are variables of the kind pthread_cond_t.

When a thread is waiting on a mutex it will continuously keep polling on the mutex waiting for it to get unlocked. Such behavior could lead to wastage of CPU resources. This can be prevented by using the condition variables.

The condition variables can be initialized statically

pthread_cond_t cond_var=PTHREAD_COND_INTIALIZER

or dynamically

pthread_cond_init(,).

Attribute can be left NULL if default attributes are sufficient. The only attribute condition variables have is process_shared, which indicates that the condition variable is visible to threads of other processes too.

Now to use the condition variable in a thread we have two functions

pthread_cond_wait(,);

This is called when a thread wants to wait for specific task to be completed by another thread before continuing its operations. This function should be called after locking the mutex, which automatically gets unlocked once the thread goes in to wait state.

pthread_cond_signal();

This function does the job of signaling to the thread that had called pthread_cond_wait. Note that the “condition variable” used in the signal and the wait functions should be the same. We need to lock the mutex that is shared by the threads before calling this function and unlock it after the call.

Once pthread_cond_signal is called the threas which was waiting on the function pthread_cond_wait will proceed with its execution.

The following program depicts the use of condition variables.
We create two threads
“fill”: which fills values into an array “arr”
read: Which reads the values of the array.

Now we can read from the array unless it is not filled, thus the thread read calls pthread_cond_wait, waiting for the array to be filled. On the other hand the thread “fill” calls pthread_cond_signal once it is done filling the array.Thus making sure that the threads are in synchronization.

#include #include #include pthread_mutex_t fill_mutex; int arr[10]; int flag=0; pthread_cond_t cond_var=PTHREAD_COND_INITIALIZER; void *fill() { int i=0; printf(“\nEnter values\n”); for(i=0;i

Category: Linux | Comments Off on Using condition variables in pthreads

Using condition variables in pthreads

Along with mutexes, pthreads gives us another tool for synchronization between the threads, condition variables. Condition variables are variables of the kind pthread_cond_t.

When a thread is waiting on a mutex it will continuously keep polling on the mutex waiting for it to get unlocked. Such behavior could lead to wastage of CPU resources. This can be prevented by using the condition variables.

The condition variables can be initialized statically

pthread_cond_t cond_var=PTHREAD_COND_INTIALIZER

or dynamically

pthread_cond_init(,).

Attribute can be left NULL if default attributes are sufficient. The only attribute condition variables have is process_shared, which indicates that the condition variable is visible to threads of other processes too.

Now to use the condition variable in a thread we have two functions

pthread_cond_wait(,);

This is called when a thread wants to wait for specific task to be completed by another thread before continuing its operations. This function should be called after locking the mutex, which automatically gets unlocked once the thread goes in to wait state.

pthread_cond_signal();

This function does the job of signaling to the thread that had called pthread_cond_wait. Note that the “condition variable” used in the signal and the wait functions should be the same. We need to lock the mutex that is shared by the threads before calling this function and unlock it after the call.

Once pthread_cond_signal is called the threas which was waiting on the function pthread_cond_wait will proceed with its execution.

The following program depicts the use of condition variables.
We create two threads
“fill”: which fills values into an array “arr”
read: Which reads the values of the array.

Now we can read from the array unless it is not filled, thus the thread read calls pthread_cond_wait, waiting for the array to be filled. On the other hand the thread “fill” calls pthread_cond_signal once it is done filling the array.Thus making sure that the threads are in synchronization.

#include #include #include pthread_mutex_t fill_mutex; int arr[10]; int flag=0; pthread_cond_t cond_var=PTHREAD_COND_INITIALIZER; void *fill() { int i=0; printf(“\nEnter values\n”); for(i=0;i

Category: Linux | Comments Off on Using condition variables in pthreads

Using pthread_mutex_trylock

In the mutex we saw in the post ” ” , if a mutex is locked by one thread, other threads will wait infinitesly for the mutex when pthread_mutex_lock is called. The other threads wil get out pf hte wait only when the mutex becomes available or the process is killed.
If such a behviour of infinite wait is undesirable we can use the variant pthread_mutex_trylock.

In this function the thread will try to lock the mutex, but in case the mutes in not available, it will return with an error EBUSY and will not try to acuire the lock again . If it is able to lock the mutex, the return value is 0 else it returns a non zero error value.

The following code shows the use of the function pthread_mutex_trylock. In the program, two threads are created one to write to a file and another to read from the file. The read thread is started with a little delay to allow the write thread to get access of the mutex.

Both the thread lock the muetx using pthread_mutex_trylock. The write thread is able to get access to the lock and continues with the execution of the thread. The read thread on the other hand tries to access the lock but is unaalbe to get a lock on the mutex as the write thread is holding the same. Thus it returns with an error value, because of which the thread has to be exited with our reading the file.

#include #include #include pthread_mutex_t rw_mutex; void * write(void *temp) { char *ret; FILE *file1; char *str; int retur; retur=pthread_mutex_trylock(&rw_mutex); if(retur!=0) { printf(“Unable to get lock”); } printf(“\nFile locked, please enter the message \n”); str=(char *)malloc(10*sizeof(char)); file1=fopen(“temp”,”w”); scanf(“%s”,str); fprintf(file1,”%s”,str); fclose(file1); sleep(5); pthread_mutex_unlock(&rw_mutex); printf(“\nUnlocked the file you can read it now \n”); return ret; } void * read(void *temp) { char *ret; FILE *file1; char *str; int retur; sleep(5); retur=pthread_mutex_trylock(&rw_mutex); if(retur!=0) { printf(“Unable to getlock”); return retur; } printf(“\nOpening file for reading\n”); file1=fopen(“temp”,”r”); str=(char *)malloc(10*sizeof(char)); fscanf(file1,”%s”,str); printf(“\nMessage from file is %s \n”,str); fclose(file1); pthread_mutex_unlock(&rw_mutex); return ret; } main() { pthread_t thread_id,thread_id1; pthread_attr_t attr; int ret; void *res; ret=pthread_create(&thread_id,NULL,&write,NULL); ret=pthread_create(&thread_id1,NULL,&read,NULL); pthread_join(thread_id,&res); pthread_join(thread_id1,&res); }

Save the file as mutex_trylock.c, and compile it using the flab -lpthread

$ cc -lpthread -o mutex_trylock mutex_trylock.c $ ./mutex_trylock File locked, please enter the message Hello Unable to getlock Unlocked the file you can read it now

We can see from the messages that the read thread has returned with an error and was unable to open the file as the pthread_mutex_trylock failed to get the lock.

Category: Linux | Comments Off on Using pthread_mutex_trylock

Deadlock creation and avoidence in pthreads

In the post we saw how we can use mutex to prevent simultaneous usage of the same resource by multiple threads. But usage of mutexes have to be done very carefully to make sure that the threads don’t end up in a dead lock.

A deadlock is a scenario when one thread is waiting for a resource which is held by the second thread, while the second thread is waiting for a resource held by the first thread. Thus causing both the threads to wait for each other infinitely.

To show how this situation might occur, in the following example we have used two mutexes,read_mutex and write_mutex. To gain access to the file both these mutexes have to be locked. In the code, the write thread locks write_mutex and then after a little delay tries to locks read_mutex. The read thread on the other hand locks read_mutex first and then tries to lock write_mutex.

Thus by the time the write tries to access read_mutex, it has already been locked by read thread and by the time read thread tries to lock write_mutex, it has already been locked by the write thread. Thus both the threads end up waiting infinitely for each other to unlock the mutexes and process ends up in a deadlock.

#include #include #include pthread_mutex_t read_mutex; pthread_mutex_t write_mutex; void * write(void *temp) { char *ret; FILE *file1; char *str; pthread_mutex_lock(&write_mutex); sleep(5); pthread_mutex_lock(&read_mutex); printf(“\nFile locked, please enter the message \n”); str=(char *)malloc(10*sizeof(char)); file1=fopen(“temp”,”w”); scanf(“%s”,str); fprintf(file1,”%s”,str); fclose(file1); pthread_mutex_unlock(&read_mutex); pthread_mutex_unlock(&write_mutex); printf(“\nUnlocked the file you can read it now \n”); return ret; } void * read(void *temp) { char *ret; FILE *file1; char *str; pthread_mutex_lock(&read_mutex); sleep(5); pthread_mutex_lock(&write_mutex); printf(“\n Opening file \n”); file1=fopen(“temp”,”r”); str=(char *)malloc(10*sizeof(char)); fscanf(file1,”%s”,str); printf(“\n Message from file is %s \n”,str); fclose(file1); pthread_mutex_unlock(&write_mutex); pthread_mutex_unlock(&read_mutex); return ret; } main() { pthread_t thread_id,thread_id1; pthread_attr_t attr; int ret; void *res; ret=pthread_create(&thread_id,NULL,&write,NULL); ret=pthread_create(&thread_id1,NULL,&read,NULL); printf(“\n Created thread”); pthread_join(thread_id,&res); pthread_join(thread_id1,&res); }

Save the file as mutex_deadlock.c, and compile it by passing “-lpthread” flag.

$ cc -lpthread mutex_deadlock.c -o mutex_deadlock $ ./mutex_deadlock

There will be no output as both the threads endup in a deadlock state, to get out of the execution use “cntrl + c”.

To avoid such simple deadlocks the easiest method is to make sure that all the threads access the locks in a specific order. In the above example if it is made compulsory that every thread should lock write_mutex first and then try to lock read_mutex, then the deadlock situation will not occur as only one thread will get access to write_mutex first and the same thread will be able to access read_mutex too.

The above code modified to avoid deadlock is shown below. Note that the order of acquiring lock by both the threads is the same, thus able to prevent deadlock.

#include #include #include pthread_mutex_t read_mutex; pthread_mutex_t write_mutex; void * write(void *temp) { char *ret; FILE *file1; char *str; pthread_mutex_lock(&write_mutex); sleep(5); pthread_mutex_lock(&read_mutex); printf(“\nFile locked, please enter the message \n”); str=(char *)malloc(10*sizeof(char)); file1=fopen(“temp”,”w”); scanf(“%s”,str); fprintf(file1,”%s”,str); fclose(file1); pthread_mutex_unlock(&read_mutex); pthread_mutex_unlock(&write_mutex); printf(“\nUnlocked the file you can read it now \n”); return ret; } void * read(void *temp) { char *ret; FILE *file1; char *str; pthread_mutex_lock(&write_mutex); sleep(5); pthread_mutex_lock(&read_mutex); printf(“\n Opening file \n”); file1=fopen(“temp”,”r”); str=(char *)malloc(10*sizeof(char)); fscanf(file1,”%s”,str); printf(“\n Message from file is %s \n”,str); fclose(file1); pthread_mutex_unlock(&read_mutex); pthread_mutex_unlock(&write_mutex); return ret; } main() { pthread_t thread_id,thread_id1; pthread_attr_t attr; int ret; void *res; ret=pthread_create(&thread_id,NULL,&write,NULL); ret=pthread_create(&thread_id1,NULL,&read,NULL); printf(“\n Created thread”); pthread_join(thread_id,&res); pthread_join(thread_id1,&res); }

Save the code as mutex_nodeadlock.c, compile it using “-lpthread” flag.

$ cc -lpthread mutex_nodeadlok.c -o create_nodeadlock $ ./create_nodeadlock Created thread File locked, please enter the message Hello Unlocked the file you can read it now Opening file Message from file is Hello

Thus we can successfully avoid a potential deadlock situation, by making use of the rules order of locks.

Category: Linux | Comments Off on Deadlock creation and avoidence in pthreads

Using pthread_mutex to lock and synchronize threads

pthreads are used to split a process into multiple threads and execute them concurrently. The threads should be independent of each other as far as possible, but at times the threads could be dependent on each other and they might be working on the same data.

Let us say we want to crate two threads,one to read from a file and the other to write into the same file. It is obvious that we can not read from a file unless we don’t write into it, and at any given time the file should be allowed to be accessed by only one of the two threads. That is while it is being written it should not be allowed to be read and while it is being read, it should not be opened for write.

The following program implements the above mentioned two threads, but does not do any thing to synchronize the actions of the two threads.

#include #include #include pthread_mutex_t rw_mutex; void * write(void *temp) { char *ret; FILE *file1; char *str; printf(“\nFile locked, please enter the message \n”); str=(char *)malloc(10*sizeof(char)); file1=fopen(“temp”,”w”); scanf(“%s”,str); fprintf(file1,”%s”,str); fclose(file1); return ret; } void * read(void *temp) { char *ret; FILE *file1; char *str; printf(“\n Opening file \n”); file1=fopen(“temp”,”r”); str=(char *)malloc(10*sizeof(char)); fscanf(file1,”%s”,str); printf(“\n Message from file is %s \n”,str); fclose(file1); return ret; } main() { pthread_t thread_id,thread_id1; pthread_attr_t attr; int ret; void *res; ret=pthread_create(&thread_id,NULL,&write,NULL); ret=pthread_create(&thread_id1,NULL,&read,NULL); printf(“\n Created thread”); pthread_join(thread_id,&res); pthread_join(thread_id1,&res); }

Save the adove file as pthread_file.c. Compile it using “-lpthread” falg

$ cc -lpthread pthread_file.c $./a.out Created thread Opening file Segmentation fault

We get a segmentation fault every time we execute the above program. This is because, the read thread tries to access the file which is being created by thread1 “write” and thus is still not available. When read thread accesses the file it still has not been created and thus we get a segmentation fault.

The part of the program in which multiple threads try to get access to the same resource, in this case the file, is termed as the critical section and ideally a critical section should be executed by only one thread at a any given time.

To prevent the access of the file by multiple threads at the same time we can make use of a mutex. Mutex stands for mutual exclution and as the name implies it keeps the threads mutually exclusive.

Access to the critical section is controlled by locking the mutex. That is whichever process locks the mutex first will be allowed to enter the critical section first and the other process can not enter the critical section unless the mutex is not unlocked by the first process.

Applying this to above example, both read and write threads will have to get a lock on a common mutex before getting access to the file. If we can make sure that the write thread always gets the access to the lock first then, the read thread will have to wait for the write thread to finish its operations on the file and unlock the mutex,before it can read it. Thus making sure that the segmentation fault never ocurrs.

To implement a mutex in pthreads we have to use a datatype of type pthread_mutex_t.
e.g.

pthread_mutex_t rw_mutex;

To lock the mutex we use the function pthread_mutex_lock(Address of mutex variable)
e.g.

pthread_mutex_lock(&rw_mutex)

To unlock the mutex we use the functions pthread_mutex_unlock(address of mutex variable)
e.g.
pthread_mutex_unlock(&rw_mute)

The implementation is shown in the code below.

pthread_mutex.c

#include #include #include pthread_mutex_t rw_mutex; void * write(void *temp) { char *ret; FILE *file1; char *str; pthread_mutex_lock(&rw_mutex); printf(“\nFile locked, please enter the message \n”); str=(char *)malloc(10*sizeof(char)); file1=fopen(“temp”,”w”); scanf(“%s”,str); fprintf(file1,”%s”,str); fclose(file1); pthread_mutex_unlock(&rw_mutex); printf(“\nUnlocked the file you can read it now \n”); return ret; } void * read(void *temp) { char *ret; FILE *file1; char *str; sleep(5); //Adding the delay to give time for write thread to lock the mutex pthread_mutex_lock(&rw_mutex); printf(“\nOpening file for reading \n”); file1=fopen(“temp”,”r”); str=(char *)malloc(10*sizeof(char)); fscanf(file1,”%s”,str); printf(“\nMessage from file is %s \n”,str); fclose(file1); pthread_mutex_unlock(&rw_mutex); return ret; } main() { pthread_t thread_id,thread_id1; pthread_attr_t attr; int ret; void *res; ret=pthread_create(&thread_id,NULL,&write,NULL); ret=pthread_create(&thread_id1,NULL,&read,NULL); printf(“\n Created thread”); pthread_join(thread_id,&res); pthread_join(thread_id1,&res); }

save the code as pthread_mutex.c and compile by passing the “-lpthread” flag and execute it.

$ cc -lpthread pthread_mutex.c -o pthread_mutex $ ./pthread_mutex Created thread File locked, please enter the message Hello Unlocked the file you can read it now Opening file Message from file is Hello

Category: Linux | Comments Off on Using pthread_mutex to lock and synchronize threads

Using pthread_self to find the thread id

Every thread created using pthread_create gets assigned a uniue thread id, with which it is recognized.

Note: Refer to creation of threads using pthreads in the post ” ”

The parent gets to know the thread id after the pthread_create is executed sucessfully, but while executing the thread if we want to access the thread id we have to use the function pthread_self.

The function pthread_self does not take any arguments, and returns the thread id, which is of kind pthread_t.

In the following program we are creating a thread which executes the function “hello”. In the function “hello” we have used pthread_self to find out the thread id and then printed the same. Note that pthread_t is an unsigned long data type and hence we have to use %u while printing using printf.

#include #include #include void * hello(void *temp) { char *ret; ret=”Finished”; pthread_t self_id; self_id=pthread_self(); printf(“\nHello from thread %u\n”,self_id); return ret; } main() { pthread_t thread_id,thread_id1; pthread_attr_t attr; int ret; void *res; ret=pthread_create(&thread_id,NULL,&hello,NULL); printf(“\nCreated thread %u”, thread_id); pthread_join(thread_id,&res); printf(“Thread returned: %s \n”,(char *)res); }

Save the file as self_pthread.c

Compile it using gcc by passing the “-lpthread” flag.

cc -lpthread self_pthread.c -o self_pthread ./self_ptherad Created thread 3076365168 Hello from thread 3076365168 Thread returned: Finished

We can see that the thread_id printed by the main function, parent, and the thread are the same, indicating that the value returned by pthread_self is the correct value.

Category: Linux | Comments Off on Using pthread_self to find the thread id