linux 线程 条件变量

与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。条件变量使我们可以睡眠等待某种条件出现。
条件变量是利用线程间共享的全局变量进行同步的一种机制,
主要包括两个动作:
一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。

条件的检测是在互斥锁的保护下进行的。如果条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。

pthread_cond_wait 原子调用: 等待条件变量, 解除锁, 然后阻塞 
当 pthread_cond_wait 返回,则条件变量有信号,同时上锁

等待条件有两种方式:
条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(), 
其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT

无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait() 
(或pthread_cond_timedwait(),下同)的竞争条件(Race Condition)。

mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP), 
且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前, 
mutex保持锁定状态,并在线程挂起进入等待前解锁。 在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,
以与进入pthread_cond_wait()前的加锁动作对应。

激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个; 
而pthread_cond_broadcast()则激活所有等待线程(惊群)。


例子:

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

int iCount = 0;
pthread_mutex_t mutex;
pthread_cond_t lock_cond;
void Addfunc(int _iNum)
{
    pthread_mutex_lock(&mutex);
    
    printf("now pthread %d add\n", _iNum);
    iCount++;
    printf("iCount = %d\n", iCount);  
    pthread_mutex_unlock(&mutex);
     
    if(iCount >= 20)
    {
        pthread_cond_signal(&lock_cond);
    }
}


Pth1_func(void * _pcBuffer)
{
    int i = 1;
    while(1)
    {
       
        Addfunc(i);
        sleep(1);
       
    }
}

Pth2_func(void * _pcBuffer)
{
    int i = 2;
    while(1)
    {
        Addfunc(i);
        sleep(1);
    }


}

Pth3_func(void * _pcBuffer)
{
    pthread_mutex_lock(&mutex);
    while(iCount < 20)
    {
        pthread_cond_wait(&lock_cond, &mutex); //程序第一次运行到此,进行阻塞此线程,解锁
                                                                            //接收到信号后,线程继续运行,加锁
        printf("iCount over 20, %d\n", iCount);
        iCount = 0;
        printf("pthread 3 iCount= %d\n", iCount);
    }
    pthread_mutex_unlock(&mutex);
}



int main(int argc, char * argv [ ])
{
    int iRet = 0;
    pthread_t pthread1;
    pthread_t pthread2;
    pthread_t pthread3;
    pthread_mutex_init(&mutex, NULL); 
    pthread_cond_init(&lock_cond, NULL);

    printf("start create pthread\n");
    
    iRet = pthread_create(&pthread1, NULL, (void *)&Pth1_func, NULL);
    if(iRet)
    {
        printf("creat pth_1 error\n");  
    }
    
    iRet = pthread_create(&pthread2, NULL, (void *)&Pth2_func, NULL);
    if(iRet)
    {
        printf("creat pth_2 error\n");  
    }

    iRet = pthread_create(&pthread3, NULL, (void *)&Pth3_func, NULL);
    if(iRet)
    {
        printf("creat pth_3 error\n");  
    }

    pthread_join(pthread1, NULL);
    pthread_join(pthread2, NULL);
    pthread_join(pthread3, NULL);

    return 1;    
}

 当程序运行到函数Pth3_func时,线程进行阻塞,并且解锁,此时执行线程Pth2_func和Pth1_func,对全局变量进行加一操作,当全局变量iCount的值>=20时,发送信号,使线程Pth3_func函数加锁,继续运行。






发布了35 篇原创文章 · 获赞 18 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Z_Dream_ST/article/details/79253989
今日推荐