DEV Community

Hieu Nguyen
Hieu Nguyen

Posted on • Edited on • Originally published at devsurvival.com

Synchronization and Critical Section Problem

Alt Text

What is Synchronization?

Synchronization in the context of multi-programming or multi-threaded programming is the process that coordinates access and manipulation of share data. If you have read some of my previous blogs, you would have noticed that we occasionally run into an issue where two threads are trying to access the same share data at the same time. To deal with this common issue we have to learn how to synchronize access of these share datas.

Critical Section Problem

The critical section is anywhere in code were one thread is accessing share data that could potentially be accessed by another thread. Synchronization will attempt to prevent two threads from accessing the critical section/shared data at the same time.

Implementing Synchronization

There are many ways to implement synchronization but they all follow this general pseudo code:

// Some code
.
.
.
acquire_access 
    // critical section 
    // access and update shared data
release_access
.
.
.
// some code

acquiring access will cause the thread to wait if access is being used by another thread or it will successfully acquire the access if no other thread is using it. Once the thread finished, it releases the access so another thread can use it.

The most simple implementation of this uses what is called Semaphore

sem_t mutex;
sem_init(&mutex, 0, 1);
int critical_section = 0;

//thread 1

sem_wait(&mutex);
critical_section ++;
sem_post(&mutex);

//thread 2

sem_wait(&mutex);
critical_section ++;
sem_post(&mutex);

Closer Look

we start by declarng a mutex variable. we initialize it with sem_init(&mutex, 0, 1) .The first parameter is the semaphore that we are trying to initialize, the 0 allows the semaphore to be shared between the threads, and the 1 is the value with which we want to initialize the sem_t mutex with. learn more . Always initialize a semaphore to a positive number, I will explain why a little bit later.

the snippet for thread 1 and thread 2 is very similar. We invoke sem_wait(&mutex) which is equivalent to acquire access. here is the pseudo code of how this function work

sem_wait(semaphore){
    if semaphore greater than 0
        semaphore -1
        return;
    else
        wait/sleep
}

Based on the code above, the semaphore has to be initialized to a positive number for even the first thread to access the critical section. When the first thread access the critical section, mutex = 1 , calling sem_wait will decrement the mutex and mutex = 0 and return. First thread is allow to enter critical section.

While first thread is accessing critical section, another thread attempts to go into the critical section, it calls sem_wait(&mutex), but mutex= 0 so it is put to sleep or forced to wait.

The first one finished using the critical section and call sem_post(&mutex) which is equivalent to release access. here is the pseudo code for sem_post.

sem_post(semaphore){
    semaphore + 1
    wake up the first thread in line to access the critical section  
}

After the first thread calls sem_post(&mutext), the second thread wakes up and enter the critical section and the process repeats.

Final Note

If you want to get into multi-threaded programming, understanding of this concept is crucial.

originally posted at https://www.devsurvival.com/synchronization-and-critical-section/

Top comments (0)