当前位置:网站首页>Mutex of thread synchronization (mutex)

Mutex of thread synchronization (mutex)

2022-06-26 04:05:00 StudyWinter

1 The concept of synchronization

So called synchronization , That is to start at the same time , To coordinate . Different objects , Yes “ Sync ” There is a slight difference in the way we understand it . Such as , Device synchronization , A common time reference is defined between two devices ; Database synchronization , It refers to keeping the contents of two or more databases consistent , Or keep the parts consistent as needed ; File synchronization , It refers to keeping the files in two or more folders consistent, etc .

And programming 、 The concept of synchronization in communication is slightly different from that in people's impression in life .“ Same as ” The word should mean synergy 、 assist 、 Cooperate with each other . The main idea is to coordinate the pace , Run in a predetermined order .

2  The concept of thread synchronization

Synchronization is co synchronization , Run in a predetermined order . Thread synchronization , When a thread makes a function call , Before we get results , The call does not return . At the same time, other threads to ensure data consistency , This function cannot be called .

“ Sync ” Purpose , To avoid data confusion , Resolve time related errors . actually , Not only do threads need to be synchronized , Interprocess 、 Synchronization mechanism is needed between signals . therefore , all “ Multiple flow control , Operate a shared resource together ” The situation of , All need to be synchronized .

3 Why thread synchronization

  • Shared resources , Multiple threads can operate on shared resources [ It's prone to conflict ]
  • The sequence of thread operations on shared resources is uncertain
  • cpu Processor operations on memory are generally not atomic operations

for instance :
Both threads increase the global variable 1, This operating platform requires three instructions to complete .


Read from memory to register → Register value plus 1 → Write the value of the register to memory .


If the thread at this time A The value is not written to the memory when the register is modified , Threads B Just fetching from memory will cause two operations to be actually modified only once . In other words, what the next thread does overwrites what the previous thread did . The thread was actually executed once .

4  The mutex mutex

4.1  Basic concepts

  • Linux Provides a mutex in mutex( It's also called mutex ).
  • Each thread tries to lock before operating on the resource , Only when the lock is successfully applied can it be operated , End of operation unlock .
  • Resources are still shared , Threads are also competing , But through “ lock ” Turn resource access into mutex operation , And then there's no more time-related mistakes .

Use of locks : Recommended lock ! Protect public data . All threads 【 should 】 Take the lock before accessing public data . but , The lock itself is not mandatory .

4.2  Manage shared data to achieve synchronization with the help of mutex lock

Main application function :

pthread_mutex_init
pthread_mutex_destory
pthread_mutex_lock
pthread_mutex_trylock
pthread_mutex_unlock

above 5 The return value of each function is : Successfully returns 0, Failure returns error number .pthread_mutex_t type , Its essence is a structure . To simplify understanding , The implementation details can be ignored in application , Simply look at it as an integer .pthread_mutex_t mutex; Variable mutex There are only two values :0,1.

  Use mutex( The mutex 、 The mutex ) General steps 【 a key 】

pthread_mutex_t  type .
1 pthread_mutex_t lock;  Create a lock 
2 pthread_mutex_init;  initialization  1
3 pthread_mutex_lock; Lock  1-- --> 0
4  Access shared data (stdout)
5 pthrad_mutext_unlock(); Unlock  0++ --> 1
6 pthead_mutex_destroy; Destroy the lock 

pthread_mutex_init function

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
                       const pthread_mutexattr_t *restrict attr)
//  there restrict keyword , Indicates that the content pointed to by the pointer can only be modified through this pointer 
// restrict keyword :
//  Used to limit pointer variables . The memory operation pointed to by the pointer variable qualified by this keyword , Must be done by this pointer .

Initialize mutex :

pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);                      //  The first 1 Kind of : dynamic initialization .
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;     //  The first 2 Kind of : initiate static 

pthread_mutex_destroy function

Destroy a mutex

int pthread_mutex_destroy(pthread_mutex_t *mutex);

pthread_mutex_lock function

Lock . It can be understood that mutex--( or -1), After the operation mutex The value of is 0 .

int pthread_mutex_lock(pthread_mutex_t *mutex);

pthread_mutex_unlock function

Unlock . It can be understood that mutex ++( or +1), After the operation mutex The value of is 1.

int pthread_mutex_unlock(pthread_mutex_t *mutex);

pthread_mutex_trylock function

Try to lock

int pthread_mutex_trylock(pthread_mutex_t *mutex);

Lock and unlock

lock And unlock:

lock Try to lock , If locking fails , Thread blocking , Block until other threads holding the mutex are unlocked .
unlock Active unlocking function , At the same time, all threads blocked on the lock will be awakened , As for which thread is awakened first , It depends on the priority 、 Dispatch . Default : Block first 、 Wake up first .

for example : T1 T2 T3 T4 Use a mutex lock . T1 Locking success , Other threads are blocked , until T1 Unlock . T1 After unlocking , T2 T3 T4 All awakened , And automatically try locking again .

But imagine mutex lock init The initial value of success is 1. lock The function is to mutex--. and unlock Will mutex++.

lock And trylock:

lock Lock failure blocks , Wait for the lock to release .

trylock If the lock fails, the error number will be returned directly ( Such as : EBUSY), Don't block .

Use the lock to realize mutual exclusive access to the shared area :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

//  Define global mutexes 
pthread_mutex_t mutex;

//  Initialize mutex 
// mutex = PTHREAD_MUTEX_INITIALIZER;

void *tfn(void *arg)
{
    srand(time(NULL));
    int res;
    while (1)
    {
        //  Lock 
        res = pthread_mutex_lock(&mutex);
        if (res != 0)
        {
            fprintf(stderr, "pthread_mutex_lock error:%s\n", strerror(res));
            exit(1);
        }
        printf("hello");
        //  Simulate long time operation, share resources 
        sleep(rand() % 3);
        printf("world\n");
        //  Unlock 
        res = pthread_mutex_unlock(&mutex);
        if (res != 0)
        {
            fprintf(stderr, "pthread_mutex_unlock error:%s\n", strerror(res));
            exit(1);
        }
        sleep(rand() % 3);
    }
    return NULL;
}

int main(int argc, char **argv)
{
    //  Define the thread 
    pthread_t tid;
    srand(time(NULL));

    //  Initialize mutex 
    int res = pthread_mutex_init(&mutex, NULL);
    if (res != 0)
    {
        fprintf(stderr, "pthread_mutex_init error:%s\n", strerror(res));
        exit(1);
    }

    //  Create thread 
    res = pthread_create(&tid, NULL, tfn, NULL);
    if (res != 0)
    {
        fprintf(stderr, "pthread_create error:%s\n", strerror(res));
        exit(1);
    }

    while (1)
    {
        //  Lock 
        res = pthread_mutex_lock(&mutex);
        if (res != 0)
        {
            fprintf(stderr, "pthread_mutex_lock error:%s\n", strerror(res));
            exit(1);
        }
        printf("HELLO");
        //  Simulate long time operation, share resources 
        sleep(rand() % 3);
        printf("WORLD\n");
        //  Unlock 
        res = pthread_mutex_unlock(&mutex);
        if (res != 0)
        {
            fprintf(stderr, "pthread_mutex_unlock error:%s\n", strerror(res));
            exit(1);
        }
        sleep(rand() % 3);
    }

    //  Recycle thread 
    pthread_join(tid, NULL);

    //  Destroy mutex 
    res = pthread_mutex_destroy(&mutex);
    if (res != 0)
    {
        fprintf(stderr, "pthread_mutex_unlock error:%s\n", strerror(res));
        exit(1);
    }
    return 0;
}

perform


You can see , When the main thread and the sub thread access the shared area, there is no cross output .

4.3  Tips for using mutex

matters needing attention :

Try to ensure the granularity of the lock , The smaller the better. .( Before accessing shared data , Lock . Access to the end 【 immediately 】 Unlock .)

The mutex , The essence is the structure . We can think of it as an integer . The initial value is 1.(pthread_mutex_init() Function call succeeded .)

Lock : -- operation , Blocking threads .

Unlock : ++ operation , Wake up the thread blocked on the lock .

try lock : Try to lock , success --. Failure , return . Set the error number at the same time EBUSY

原网站

版权声明
本文为[StudyWinter]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206260356299058.html