Pthreads

Pthreads

Example of multithreaded programming in C without mutual exclusion/locks
#include <pthread.h> #include <stdio.h> int count = 0; void* run_thread() {    pthread_t thread_id = pthread_self();    printf("Thread %u: Current value of count = %dn", thread_id, count);    printf("Thread %u incrementing count ...n");    count++;    sleep(1);    printf("Value of count after incremented by thread %u = %dn", thread_id, count);    pthread_exit(NULL); }   int main (int argc, char *argv[]) {    pthread_t thread_array[4];    int i = 0, ret, thread_num = 4;    for (i = 0; i < thread_num; i++) {       if ((ret = pthread_create(&thread_array[i], NULL, run_thread, NULL)) == -1) {          printf("Thread creation failed with return code: %d", ret);          exit(ret);       }    }       pthread_exit(NULL); }

Output:

Thread 2: Current value of count = 0
Thread 2 incrementing count …
Thread 3: Current value of count = 1
Thread 3 incrementing count …
Thread 4: Current value of count = 2
Thread 4 incrementing count …
Thread 5: Current value of count = 2
Thread 5 incrementing count …
Value of count after incremented by thread 4 = 4
Value of count after incremented by thread 3 = 4
Value of count after incremented by thread 5 = 4
Value of count after incremented by thread 2 = 4

Explanation:

In the above code, we use Pthreads interface for implementing the thread functionality in C, although I won’t be going through the Pthread methods here, the above code creates four threads (line 27 – 31) which invokes the function run_thread function whose return type is a pointer to void (line 11) where all threads increment the global count value (line 16), sleeps for a second and prints the value of count after its incremented by that thread (lines 11 – 20), since context switch occurs when threads sleep, the other threads increment the value by the time a thread sleeps and so on, as a result the threads couldn’t print the value of count correctly after its incremented by them, this problem can be solved using mutual exclusion construct as shown below.

Example of multithreaded programming in C with mutual exclusion/locks

#include <pthread.h>
#include <stdio.h>

int count = 0;
pthread_mutex_t thread_lock;

void* run_thread()
{
   pthread_mutex_lock(&thread_lock);
   pthread_t thread_id = pthread_self();
   printf(“Thread %u: Current value of count = %dn”, thread_id, count);
   printf(“Thread %u incrementing count …n”);
   count++;
   sleep(1);
   printf(“Value of count after incremented by thread %u = %dn”, thread_id, count);
   pthread_mutex_unlock(&thread_lock);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t thread_array[4];
   int i = 0, ret, thread_num = 4;

   for (i = 0; i < thread_num; i++) {
      if ((ret = pthread_create(&thread_array[i], NULL, run_thread, NULL)) == -1) {
         printf(“Thread creation failed with return code: %d”, ret);
         exit(ret);
      }
   }   
   pthread_exit(NULL);
}

 

Output:

Thread 2: Current value of count = 0
Thread 2 incrementing count …
Value of count after incremented by thread 2 = 1
Thread 5: Current value of count = 1
Thread 5 incrementing count …
Value of count after incremented by thread 5 = 2
Thread 4: Current value of count = 2
Thread 4 incrementing count …
Value of count after incremented by thread 4 = 3
Thread 3: Current value of count = 3
Thread 3 incrementing count …
Value of count after incremented by thread 3 = 4

Explanation:

The above code is similar to the Listing 1.1 with mutual exclusion construct to ensure exclusive access to the portion of code which would be executed only by a single thread to completion without context switching, a thread acquires a lock with the call to pthread_mutex_lock (line 14) and releases the lock using pthread_mutex_unlock (line 21), both methods take a pthread_mutex_t member thread_lock on which the lock is acquired or released (line 10), thus mutual exclusion ensures that all atomic operations run to completion without context switching.

 

Example of multithreaded programming in C with semaphore:

#include <pthread.h>
#include <stdio.h>

int count = 0;

sem_t mutex;

void* run_thread()
{
   sem_wait(&mutex);       /* down semaphore */
   pthread_t thread_id = pthread_self();
   printf(“Thread %u: Current value of count = %dn”, thread_id, count);
   printf(“Thread %u incrementing count …n”);
   count++;
   sleep(1);
   printf(“Value of count after incremented by thread %u = %dn”, thread_id, count);
   sem_post(&mutex);       /* up semaphore */
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t thread_array[4];
   int i = 0, ret, thread_num = 4;

 

  sem_init(&mutex, 0, 1);      /* initialize mutex to 1 - binary semaphore */

                               /* second param = 0 - semaphore is local */

   for (i = 0; i < thread_num; i++) {
      if ((ret = pthread_create(&thread_array[i], NULL, run_thread, NULL)) == -1) {
         printf(“Thread creation failed with return code: %d”, ret);
         exit(ret);
      }
   }   

   sem_destroy(&mutex); /* destroy semaphore */

    pthread_exit(NULL);
}

 

Condition Variable
     In typical use, a condition expression is evaluated under the protection of a mutex lock. When the condition expression is false, the thread blocks on the condition variable. The condition variable is then signaled by another thread when it changes the condition value. This causes one or all of the threads waiting on the condition to unblock and to try to acquire the mutex lock again.

int foo = 0;

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

 

void foo_ready()

{

    pthread_mutex_lock(&mutex);

    while (foo != 1) {

        pthread_cond_wait(&cond, &mutex);

    }

    pthread_mutex_unlock(&mutex);

}

 

void foo_initializer()

{

    pthread_mutex_lock(&mutex);

    if (foo == 0)

        foo = 1;       /* This must only be done once. */

    pthread_cond_broadcast(&cond);

    pthread_mutex_unlock(&mutex);

}

 

 

Comments