线程同步之条件变量

相关函数

  1. int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);初始化一个条件变量;也可以直接定义的方式初始化:pthread_cond_t cond = PTHREAD_COND_INITIALIZER(只能使用默认参数设定);
  2. int pthread_cond_broadcast(pthread_cond_t *cond); 发送一个信号到等待该条件变量的单个线程;
    int pthread_cond_signal(pthread_cond_t *cond); 广播发送信号到所有等待该条件变量的线程;
  3. int pthread_cond_timedwait(pthread_cond_t *restrict cond,
    pthread_mutex_t *restrict mutex,
    const struct timespec *restrict abstime);
    int pthread_cond_wait(pthread_cond_t *restrict cond,
    pthread_mutex_t *restrict mutex);
    等待该条件变量的信号,调用该函数会先解锁mutex并阻塞,所以在线程中先必须加锁;当等到信号时,就加锁mutex,唤醒线程;
  4. int pthread_cond_destroy(pthread_cond_t *cond); 销毁条件变量,前提是已经没有线程等待该条件变量;

条件变量示例

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

#include <time.h>
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

#define DBG_PRINT(fmt, args...) {printf("%s %d ", __FUNCTION__, __LINE__);printf(fmt,##args);}
#define DBG_LINE() {printf("%s %d\n", __FUNCTION__, __LINE__);}

typedef unsigned char BOOL;
#define TRUE 1
#define FALSE 0

/**
 * [msDelay_select 用select()实现的ms级别线程休眠]
 * @param msTime [休眠线程msTime时间,单位毫秒]
 */
void msDelay_select(unsigned msTime)
{
    struct timeval time;
    if(msTime == 0)
    {
        DBG_PRINT("delay time can not be 0!\n");
        return;
    }

    if(msTime>=1000)
    {
        time.tv_sec = msTime/1000;
        time.tv_usec = (unsigned long)(msTime%1000)*1000UL;
    }
    else
    {
        time.tv_sec = 0;
        time.tv_usec = (unsigned long)msTime*1000UL;
    }

    select(0, NULL, NULL, NULL, &time);
}

static pthread_mutex_t mutexID; // = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond1ID, cond2ID;
//static pthread_cond_t cond1ID = PTHREAD_COND_INITIALIZER;
//static pthread_cond_t cond2ID = PTHREAD_COND_INITIALIZER;
static char testStr[1000];
BOOL mutexInit(void)
{
    int ret = 0;
    ret = pthread_mutex_init(&mutexID, NULL);
    if(ret != 0)
    {
        DBG_PRINT("pthread_mutex_init failed! errno:%s\n", strerror(ret));
        return FALSE;
    }

    return TRUE;
}

BOOL condInit(void)
{
    int ret = 0;
    ret = pthread_cond_init(&cond1ID, NULL);  
    if(ret != 0)
    {
        DBG_PRINT("pthread_cond_init failed! errno:%s\n", strerror(ret));
        return FALSE;
    }

    ret = pthread_cond_init(&cond2ID, NULL);  
    if(ret != 0)
    {
        DBG_PRINT("pthread_cond_init failed! errno:%s\n", strerror(ret));
        return FALSE;
    }

    return TRUE;
}

void *testThread1(void* arg)
{
    int ret = -1;
    while(1)
    {
        pthread_mutex_lock(&mutexID);
        DBG_LINE();
        /**
         * pthread_cond_wait()会先尝试等待该条件变量,如果等不到,就解锁mutexID,然后线程进入阻塞;
         * int pthread_cond_timedwait(pthread_cond_t *restrict cond, 
             pthread_mutex_t *restrict mutex, 
            const struct timespec *restrict abstime);是对应的设定超时等待的函数;
         */
        ret = pthread_cond_wait(&cond1ID, &mutexID);
        DBG_LINE();
        DBG_PRINT("pthread_cond_wait:%s\n", strerror(ret));
        DBG_PRINT("The string is:%s\n", testStr);
        pthread_mutex_unlock(&mutexID);
    //  msDelay_select(50);
    }

    return NULL;
}

void *testThread2(void* arg)
{
    int ret = -1;
    while(1)
    {
        pthread_mutex_lock(&mutexID);
        DBG_LINE();
        ret = pthread_cond_wait(&cond2ID, &mutexID);
        DBG_LINE();
        DBG_PRINT("pthread_cond_wait:%s\n", strerror(ret));
        DBG_PRINT("The string is:%s\n", testStr);
        pthread_mutex_unlock(&mutexID);
    //  msDelay_select(50);
    }

    return NULL;
}

void *testThread3(void* arg)
{
    int ret = -1;
    while(1)
    {
        pthread_mutex_lock(&mutexID);
        DBG_LINE();
        ret = pthread_cond_wait(&cond2ID, &mutexID);
        DBG_LINE();
        DBG_PRINT("pthread_cond_wait:%s\n", strerror(ret));
        DBG_PRINT("The string is:%s\n", testStr);
        pthread_mutex_unlock(&mutexID);
    //  msDelay_select(50);
    }

    return NULL;
}

int main(int argc, const char*argv[])
{
    int ret = 0;
    pthread_t thread1ID, thread2ID, thread3ID;

    mutexInit();
    condInit();

    ret = pthread_create(&thread1ID, NULL, testThread1, NULL);
    if(0 != ret)
    {
        DBG_PRINT("pthread_create failed, errno:%s\n", strerror(ret));
        return -1;
    }
    ret = pthread_create(&thread2ID, NULL, testThread2, NULL);
    if(0 != ret)
    {
        DBG_PRINT("pthread_create failed, errno:%s\n", strerror(ret));
        return -1;
    }
    ret = pthread_create(&thread3ID, NULL, testThread3, NULL);
    if(0 != ret)
    {
        DBG_PRINT("pthread_create failed, errno:%s\n", strerror(ret));
        return -1;
    }

    pthread_detach(thread1ID);
    pthread_detach(thread2ID);
    pthread_detach(thread3ID);
    DBG_LINE();
    while(1)
    {
        pthread_mutex_lock(&mutexID);
        DBG_LINE();
        memset(testStr, 0x00, 1000);
        fgets(testStr, 999, stdin);
        if(0 == strncmp(testStr, "exit", 4))
        {
            pthread_mutex_unlock(&mutexID);
            DBG_LINE();

            return -1;
        }
        else if(0 == strncmp(testStr, "task1", 5))
        {
            DBG_LINE();
            /**
             * 发送信号到等待条件变量cond1ID的某一个线程;
             */
            pthread_cond_signal(&cond1ID);
        }
        else if(0 == strncmp(testStr, "task2", 5))
        {
            DBG_LINE();
            /**
             * 发送信号到等待条件变量cond2ID的某一个线程;只会有一个线程解除阻塞,哪个线程先pthread_cond_wait,
             * 就哪个线程先解除阻塞;
             */
            pthread_cond_signal(&cond2ID);
        }
        else if(0 == strncmp(testStr,"broadcast", 9))
        {
            DBG_LINE();
            /**
             * 广播信号到等待条件变量cond2ID的所有线程,让等待cond2ID并且在阻塞中的所有线程重新获取mutex后运行;
             */
            pthread_cond_broadcast(&cond2ID);
        }
        DBG_LINE();
        pthread_mutex_unlock(&mutexID);
        msDelay_select(200);
    }

    return 0;
}

编译运行,结果如下图:
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值