×

Search anything:

Mutex and critical section

Binary Tree book by OpenGenus

Open-Source Internship opportunity by OpenGenus for programmers. Apply now.

A351_Mutex-and-Semaphore-in-OS2-1

In this article at OpenGenus, we have explained the concept of Mutex and critical section along with a C++ code for demonstration.

Table of contents:

  1. Why using threads?
  2. What is a critical section?
  3. C++ Implementation

Why using threads?

Working on multiple processes is characterized by two things:

  • Concurrency: where two or more processes work on separate things doing different things at the same time.
  • Isolation: Processes are isolated from one another; meaning their memory is separate (so if one crashes, the other will work just fine).

We use threads to control multiple different flows of work that overlap in time. Working on multiple threads on the other hand is characterized by only concurrency. Meaning working on two different things concurrently but without the isolation (i.e. without separating memory frames). Threads have different call stacks but are in the same process, hence same memory space.

Due to being in the same memory space, one thread can write in the space of the other thread. That could be a grace or a disaster.

What is a critical section?

Writing i++ in HLL actually gets executed in three steps;

int temp;
temp = i+1;
i = temp;

If more that one thread is trying to update the value of i it could well happen that the three steps don't get completed before the context is switched to the other thread. As a result, the operation of that thread will be incomplete. Therefore, the section of the code that must be completed from top to bottom is called a critical section and must be exclusive to one thread hence the term MUTEX lock (or just lock). A thread won't be able to access a critical section unless its lock is released. A MUTEX lock is a computing abstraction that allows one thread to exclude other threads from a critical section of the code. A lock can only be owned to one thread until it releases it.

C++ Implementation

I use POSIX threads (aka pthreads). POSIX Threads is an API defined by the IEEE standard POSIX.1c, Threads extensions (IEEE Std 1003.1c-1995). POSIX threads are implemented with a pthread.h header and a thread library typically bundled as libpthread.

#include <pthread.h>
#include <iostream>

/* x is a global variable to be updated by two different 
threads. Each thread has a separate function */
int x = 0;

void* threadFunction1(void* arg){
    for (int i=0;i<150000;i++){
        //Critical section
        pthread_mutex_lock((pthread_mutex_t*) arg);
        x++;
        pthread_mutex_unlock((pthread_mutex_t*) arg);
    }
    return NULL;
}

void* threadFunction2(void* arg){
    for (int i=0;i<5;i++){
        //Critical section
        pthread_mutex_lock((pthread_mutex_t*) arg);
        x++;
        pthread_mutex_unlock((pthread_mutex_t*) arg);
    }
    return NULL;
}

int main(){
    //Declare two threads
    pthread_t t1, t2;
    /* Declare and initialize a lock to the default 
    values and thus makes the lock usable */
    pthread_mutex_t lock1=PTHREAD_MUTEX_INITIALIZER;

    pthread_create(&t1, NULL, threadFunction1, &lock1);
    pthread_create(&t2, NULL, threadFunction2, &lock1);
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    std::cout<<"x="<<x<<std::endl;
    return 0;
}
Mutex and critical section
Share this