C language scrap 2: Use pure software to replace Mutex mutex

I. Introduction

In the Linux system, when multiple threads execute in parallel , if you need to access the same resource , you need to use the synchronization primitives provided by the operating system to protect you where you access the resource . Synchronization primitives include: mutexes, condition variables, semaphores, etc. The protected code is called "critical section" .

This is a very formal process, and we basically do this.

Have you ever wondered how much impact these synchronization primitives will have on the execution efficiency of the code ? Is it possible not to use these mechanisms provided by the operating system, but to use other pure software methods to achieve the purpose of protecting the critical section?

In this article, we introduce the Peterson algorithm , which may not be practical, but it can bring us some thinking and improve our programming meta-skills .

2. Introduction to Peterson Algorithm

This algorithm is mainly used to solve the protection problem of the critical section . We know that a critical section must guarantee three conditions:

  1. Mutually exclusive access: at any one time, only one thread can enter the critical section;
  2. Idle let in: When no thread is executing the code in the critical section, you must select one of the threads that apply to enter the critical section and let it enter the critical section;
  3. Limited waiting: When a thread applies to enter the critical section, it cannot wait indefinitely, and must obtain permission to enter the critical section within a limited time. In other words, no matter how low its priority is, it should not starve to death at the entrance of the critical zone.

Peterson's algorithm is a concurrent programming algorithm that implements mutual exclusion locks. It can control two threads to access a shared user resource without access conflict.

Peterson's algorithm is based on the LockOne and LockTwo algorithms of two-threaded mutual exclusive access.

  1. The LockOne algorithm uses a flag boolean array
  2. LockTwo uses a turn integer

Both of these two algorithms achieve mutual exclusion, but both have the possibility of deadlock . Peterson's algorithm combines these two algorithms and perfectly implements the dual-thread mutual exclusion problem with software.

The algorithm is explained as follows

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-1aTmiPkc-1617241079938)(http://iottown.sewain100.cn/iot32_01)]

Two important global variables :

Flag array: There are 2 Boolean elements, which respectively represent whether a thread applies to enter the critical area;
turn: If both threads apply to enter the critical area, this variable will determine which thread to enter the critical area;

Three, test code

// 被 2 个线程同时访问的全局资源
static int num = 0; 

BOOL flag[2] = { 0 };
int turn = 0;

void *thread0_routine(void *arg)
{
    for (int i = 0; i < 1000000; ++i)
    {
        flag[0] = TRUE;
        turn = 1;
        while (TRUE == flag[1] && 1 == turn);

        // 临阶区代码
        num++; 
        
        flag[0] = FALSE;
    }
    
    return NULL;
}

void *thread1_routine(void *arg)
{
    for (int i = 0; i < 1000000; ++i)
    {
        flag[1] = TRUE;
        turn = 0;
        while (TRUE == flag[0] && 0 == turn);

        // 临阶区代码
        num++;
        
        flag[1] = FALSE;
    }

    return NULL;
}

The initial value of the global resource num is 0 , and the two programs are incremented by 1 million times respectively , so the final result should be 2 million, and the actual test result is also true.

Fourth, the impact of Mutex mutex locks on code execution efficiency

1. In a single thread: the effect of Mutex mutex on code execution efficiency

for (int i = 0; i < 1000000; ++i)
{
    num++;
}

The above code takes about 1.8ms-3.5ms .

for (int i = 0; i < 1000000; ++i)
{
    pthread_mutex_lock(&mutex);
    num++;
    pthread_mutex_unlock(&mutex);
}

The above code takes about 23.9ms-38.9ms . It can be seen that the effect of locking and unlocking on code execution efficiency is still very obvious .

2. In multithreading: the influence of Mutex mutex on code execution efficiency

void *thread0_routine(void *arg)
{
    for (int i = 0; i < 1000000; ++i)
    {
        pthread_mutex_lock(&mutex);
        num++;
        pthread_mutex_unlock(&mutex);
    }
    
    return NULL;
}

void *thread1_routine(void *arg)
{
    for (int i = 0; i < 1000000; ++i)
    {
        pthread_mutex_lock(&mutex);
        num++;
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

time consuming:

thread0: diff = 125.8ms
thread1: diff = 129.1ms

3. In two threads, use Peterson's algorithm to protect the critical section

time consuming:

thread1: diff = 1.89ms
thread0: diff = 1.94ms

Five, summary

Peterson's algorithm uses pure software to protect the critical section, which shows better performance than using the mutex provided by the operating system.

But it also has a disadvantage : it can only be used in 2 threads, but because it has nothing to do with the platform , in some special occasions, it may be able to be used for our use!


Good articles should be forwarded ; the more you share, the luckier you are!


Recommended reading

[C language]
1. C language pointer-from the underlying principle to fancy skills, with pictures and codes to help you explain thoroughly
2. The original gdb underlying debugging principle is so simple
3. Step by step analysis-how to use C to achieve object-oriented programming
4. A weapon to improve code compulsion: macro definition-from entry to abandonment
5. Use setjmp and longjmp in C language to implement exception capture and coroutine

[Application design]
1. They all say that the software architecture should be layered and divided into modules, and how to do it (1)
2. They all say that the software architecture needs to be layered and divided into modules, and how to do it (2)
3. IoT gateway Development: MQTT message bus-
based design process (Part 1) 4. IoT gateway development: MQTT message bus-based design process (Part 2)
5. My favorite method of communication between processes-message bus

[Operating System]
1. Why do spacecraft and missiles prefer to use microcontrollers instead of embedded systems?

[Internet of Things]
1. Those things about encryption and certificates
2. Deepen the LUA scripting language, let you fully understand the principle of debugging

[Nonsense] 1. Based
on my failed career experience: a few tips for technicians who are new to the workplace

Guess you like

Origin blog.csdn.net/u012296253/article/details/115366895