Talking about condition variables again - from entry to renunciation

3cff2ddd0fb70e6f12cffff4939031d2.png

Talking about condition variables again - from entry to renunciation


C language -- condition variable

Condition variables wait for a condition to occur in a sleep mode in a thread;

Condition variables are a mechanism for synchronization using global variables shared between threads:

  • A thread waiting for "condition of condition variable is true" is suspended

  • Another thread makes "condition true"

The use of condition variables is always combined with a mutex;

**What it does:** Use a condition variable to atomically block a thread until a certain condition is true


The functions we generally use are:

#include <semaphore.h>
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) ;
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_destroy(pthread_cond_t *cond);

Case number one

Code:

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

pthread_t t1;
pthread_t t2;

pthread_mutex_t mutex;
pthread_cond_t cond;

int i=0;

void* Process1(void* arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        i++;
        if(i%5 == 0)
        {
            pthread_cond_signal(&cond);
        }
        else
        {
            printf("this is Process1\n");
        }
        pthread_mutex_unlock(&mutex);
        sleep(2);
    }
}


void* Process2(void* arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond,&mutex);
        printf("this is Process2,i=%d\n",i);
        pthread_mutex_unlock(&mutex);
        sleep(2);
    }
}

int main()
{
    pthread_cond_init(&cond,NULL);
    pthread_mutex_init(&mutex,NULL);
    pthread_create(&t1,NULL,Process1,NULL);
    pthread_create(&t2,NULL,Process2,NULL);
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    return 0;
}

result:

root@iZuf67on1pthsuih96udyfZ:~/C++/C++_test/Progress/cond# ./test1 
this is Process1
this is Process1
this is Process1
this is Process1
this is Process2,i=5
this is Process1
this is Process1
this is Process1
this is Process1
this is Process2,i=10
this is Process1
this is Process1
^C

Control the output of the thread through condition variables;


The above is to use condition variables to control threads in C language. In C++, the same mechanism is also provided in the standard library, which is more convenient to use than that of C language, but the principle is still the same;

C++ condition variable

The C++ standard library is in <condition_variable>

The principle is similar to that in the C language

  • Contains <mutex> and <condition_variable>, declares a mutex and a condition_variable variable

  • The thread that notifies "condition is met" must call notify_one() or notify_all(), and wake up a waiting condition variable when the condition is met;

  • A thread waiting for "conditions to be met" must call wait(), which can make the thread sleep when the condition is not met, and wake up to process the corresponding task when a notification is received;

C++ use cases

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <unistd.h>

using namespace std;

//全局条件变量
condition_variable cond;
mutex _mutex;
int count = 0;

void fun1()
{
    while(1)
    {
        count++;
        unique_lock<mutex>lock(_mutex);
        if(count%5 == 0)
        {
            cond.notify_one();
        }
        else
        {
            cout<<"this is fun1,count="<<count<<endl;
        }
        lock.unlock();
        sleep(1);
    }
}

void fun2()
{
    while(1)
    {
        unique_lock<mutex>lock(_mutex);
        cond.wait(lock);
        cout<<"this is fun2,count="<<count<<endl;
        lock.unlock();
        sleep(2);
    }
}

int main()
{
    thread t1(fun1);
    thread t2(fun2);
    t1.join();
    t2.join();
    return 0;
}

result:

root@iZuf67on1pthsuih96udyfZ:~/C++/C++_test/Progress/cond# g++ -std=c++11 test2.cpp -o test2 -lpthread
root@iZuf67on1pthsuih96udyfZ:~/C++/C++_test/Progress/cond# ./test2
this is fun1,count=1
this is fun1,count=2
this is fun1,count=3
this is fun1,count=4
this is fun2,count=5
this is fun1,count=6
this is fun1,count=7
this is fun1,count=8
^C

So far, I have basically reviewed the usage of condition variables in C and C++, but in practical applications. What's the use of it?

Maybe people who have worked for a long time have come into contact with more, but for many Xiaobai, or people who have just graduated and have just started working, they will not have much contact with them. Here's an example:

If multiple threads need to be used in a project, the simplest is that when using queues, we always need to lock while writing and reading, but our threads must always be idling on the queue. Detect whether there is data, but this often results in high CPU usage and waste of resources. In this case, we can use condition variables to control the loop of threads and reduce resource usage; of course, there are many scenarios worthwhile. To explore, there are many technologies that can solve this problem, I hope everyone can explore and move forward together;

problem thinking

The use of C and C++ is introduced above, but there are still some doubts

Question: Why pthread_cond_waitis the lock added before, but pthread_cond_signalit can still be locked?

First look at a picture I found online:

909a678a0d78646b3a7f51df0fde95e2.png

From this picture, we found a phenomenon that the pthread_cond_waitfunction memory unlocks the lock and blocks the sleep operation. After the blocking is completed, the locking operation is performed again; that is, during the pthread_cond_waitblocking period, pthread_cond_signalthe locking and unlocking operations can be performed, here are not conflicting;

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324213348&siteId=291194637