Reproduced Linux multi-threaded conditional variable synchronization

Source: Internet
Author: User
Tags mutex

The condition variable is another way of thread synchronization, in fact, the condition variable is the underlying implementation of the semaphore, which means that the use of conditional variables can have greater degrees of freedom, but also require more careful synchronization operation. The condition used by the condition variable itself needs to be secured with a mutex, and the thread must first lock the mutex before changing the condition state , and other threads will not perceive the change until the mutex is acquired, because the mutex must be locked before the condition can be evaluated.

Model
#include<pthread.h>pthread_cond_t cond              //准备条件变量pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化静态的条件变量pthread_cond_init() //初始化一个动态的条件变量pthread_cond_wait() //等待条件变量变为真pthread_cond_timedwait() //等待条件变量变为真,等待有时间限制。pthread_cond_signal() //至少唤醒一个等待该条件的线程pthread_cond_broadcast() //唤醒等待该条件的所有线程pthread_cond_destroy() //销毁一个条件变量
Pthread_cond_init ()
//初始化一个动态的条件变量//成功返回0,失败返回error numberint pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);

cond: Conditional variable pointer, where the Restrict keyword is used
attr: Conditional variable property pointer, default property assigned NULL

Pthread_cond_wait ()/pthread_cond_timedwait ()
 //the wait condition variable is true. Received Pthread_cond_broadcast () or pthread_cond_signal () on Wake //successfully returned 0, failed to return error Numberint pthread_cond_wait  (pthread_cond_t *restrict cond, pthread_mutex_t *restrict Mutex"); int pthread_cond_timedwait (pthread_cond_t *restrict cond, pthread_mutex_t *restrict Mutex, const struct timespec *restrict abstime)            

Conditional variables in a multithreaded program, because each thread can access most of the process resources, so we have to ensure that the use of public resources can be controlled, before a thread starts to use the public resources to try to obtain a mutex, after use to release the mutex, This ensures that each public resource can only be used by one thread at a time and is controlled to some extent, but this does not solve the problem of synchronization, consider the following two threads:

Q=create_queue();pthread_t mutex//线程A,入队while(1){    lock(mutex);    in_queue(Q);    unlock(mutex);}//线程B,出队while(1){ lock(mutex); out_queue(Q); unlock(mutex);}

The code above can be mutually exclusive for two threads, that is, only one thread is using the public resource-queue at the same time. But if thread B acquires a lock, but the queue is empty, its out_queue () is meaningless, so we need a way to synchronize two threads here: only when there is data in the queue.
We design such a logic:

//线程B,出队while(1){    lock(mutex);    if(队列是空,线程不应该执行){ 释放锁; continue; } out_queue(Q); unlock(mutex);}

This program solves the problem, even if thread B grabs the mutex, but if the queue is empty, he releases the lock to allow two threads to re-grab the lock, hoping that thread A can grab and put a data into it.
But this logic has another problem, is the problem of multithreading concurrency, it is likely that a situation is: thread B grabbed the lock, found no data, release lock ----thread A immediately grabbed the lock and put a data , thread B execution continue, obviously, In this case, it should not be continue, because the condition that thread B wants is satisfied immediately after releasing the lock, and it misses the condition.
So, we want a reverse logic:

//线程B,出队while(1){    lock(mutex);    if(队列是空,线程不应该执行){ continue; 释放锁; } out_queue(Q); unlock(mutex);}

Obviously there is a fatal problem with this approach: once continue, thread B does not get a lock on its own, so thread a cannot grab the lock, and B continues to lock to form a deadlock!
Finaly, we want to see a function FCN, if the condition is not satisfied, can simultaneously release the Lock + Stop the execution thread, if the condition is satisfied, the lock that I acquired at that time

//线程B,出队while(1){    lock(mutex);    fcn(当前线程不应该执行,mutex)     //if(当前线程不应该执行){释放锁“同时” continue;} out_queue(Q); unlock(mutex);}

OK, this is the principle of pthread_cond_wait (), but it turns continue into a "dormant" this OS-responsible operation, can greatly save resources.
Of course, the condition of thread execution is that it is difficult to pass in a function as a parameter, and the POSIX multithreaded model uses the system-provided "condition variable" + "our own defined conditions" to determine whether a thread should execute the next content. "Conditional variables" are only true and false , so a typical multithreaded synchronization structure is as follows

//线程B,出队while(1){    lock(mutex);    while(条件不满足) pthread_cond_wait(cond,mutex) //获得互斥锁可以同时保护while里的条件和cond的判断,二者总是用一把锁保护,并一同释放 //cond为假,就休眠同时释放锁,等待被cond为真唤醒,把自己获得的锁拿回来 //拿回自己的锁再检查线程执行条件,条件不满足继续循环,直到条件满足跳出循环 //这个函数是带着"线程的执行条件为真"+"cond为真"走出循环的 //这个函数返回后cond被重新设置为0 out_queue(Q); unlock(mutex);}
Pthread_cond_braoadcast ()/pthread_cond_signal ()
//使条件变量为真并唤醒wait中的线程,前者唤醒所有wait的,后者唤醒一个//成功返回0,失败返回error numberint pthread_cond_broadcast(pthread_cond_t *cond);int pthread_cond_signal(pthread_cond_t *cond);
Pthread_cond_destroy ()
//销毁条件变量//成功返回0,失败返回error numberint pthread_cond_destroy(pthread_cond_t *cond);
Example-thread pool
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Thread.h#Ifndef __thread_h__#Define __thread_h__#Define Thread_num 3#Define Task_num 100typedef struct{Per-node encapsulation format, FCN is a user-defined function, ARG is a user-defined function parameter pointer, which guarantees that the generality is declared void void* (*FCN) (void* Arg); void* Arg;} Task_t;typedef struct{The parameter structure of the user-defined function int x;} argfcn_t;#define LQ_DATA_T task_t*#Define lq_data_t task_t#endif__thread_h__\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Lqueue.c#Include"Thread.h"#Include"Lqueue.h"#Include<stdlib.h>...\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Thread_pool.c#Include<stdio.h>#Include<stdlib.h>#Include<string.h>#Include<pthread.h>#Include"Thread.h"#Include"Lqueue.h"Mutex and condition variable pthread_mutex_t lock;pthread_cond_t cond;Global table lqueue_t* Q;The task for each thread must be the function pointer of this form void* do_task (void* p) {task_t data; int ret=0; While1) {Pthread_mutex_lock (&lock); while (Is_empty_lqueue (Q)) {Everyone receives the broadcast, because the delay, may wake up several, must judge whether oneself pthread_cond_wait (&cond,&lock);First grab the lock and wake Up} ret=out_lqueue (Q,&data); Pthread_mutex_unlock (&lock); DATA.FCN (DATA.ARG); }}Create thread pool void Create_pool (void) {Initialize Queue q=create_lqueue ();Initializes the mutex Pthread_mutex_init (&lock,null);Initialize the condition variable pthread_cond_init (&cond,null); int i=thread_num; pthread_t Tid[thread_num]; while (i--) pthread_create (&tid[i],null,do_task,null);}Prepare function void* FCN (void* parg) {//user-defined functions that require thread execution argfcn_t* i= (argfcn_t*) parg; printf ( "this is task1\n "); printf ( "task1:%d\n", i->x);} //Add task void Pool_add_task (void* (*PFCN) (Void*parg), Void*arg) {task_t task; TASK.FCN=PFCN; Task.arg=arg; In_lqueue (Q,task); Pthread_cond_signal (&cond); //added a task, signal better}int main (int argc, const char *argv[]) {// Create thread pool Create_pool (); //preparation parameters argfcn_t ARGFCN; Argfcn.x=5; //Add Task Pool_add_task (FCN, (void*) &ARGFCN); pool_add_ Task (FCN, (void*) &ARGFCN); Pool_add_task (FCN, (void*) 0;             

(reproduced) Linux multithreaded conditional variable synchronization

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.