posix多线程--条件变量

条件变量是用来通知共享数据状态信息的。

 

1.条件变量初始化两种方式:
(1)静态初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
代码示例如下:

#include <pthread.h>
typedef struct my_struct_tag {
    pthread_mutex_t     mutex;  /* Protects access to value */
    pthread_cond_t      cond;   /* Signals change to value */
    int                 value;  /* Access protected by mutex */
} my_struct_t;

my_struct_t data = {
    PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};

int main (int argc, char *argv[])
{
    return 0;
}

(2)动态初始化
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *condattr);
int pthread_cond_destroy(pthread_cond_t *cond);
代码示例如下:

#include <pthread.h>

typedef struct my_struct_tag {
    pthread_mutex_t     mutex;  /* Protects access to value */
    pthread_cond_t      cond;   /* Signals change to value */
    int                 value;  /* Access protected by mutex */
} my_struct_t;

int main (int argc, char *argv[])
{
    my_struct_t *data;
    int status;
    data = malloc (sizeof (my_struct_t));
    status = pthread_mutex_init (&data->mutex, NULL);
    status = pthread_cond_init (&data->cond, NULL);
    status = pthread_cond_destroy (&data->cond);
    status = pthread_mutex_destroy (&data->mutex);
    (void)free (data);
    return status;
}

2.等待条件变量
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,struct timespec *expiration);
当线程等待条件变量时,它必须将相关互斥量锁住。在阻塞线程之前,条件变量等待操作将解锁互斥量,而在重新返回线程之前,会再次锁住互斥量。

 

3.唤醒条件变量
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
在发送信号时也必须锁住互斥量,如果互斥量不被锁住,任何线程可以在被唤醒线程之前锁住互斥量。这将是一个产生被拦截唤醒的根源。例如,一个低优先级的线程可能锁住了互斥量,使高优先级的线程无法被其他线程唤醒,延迟了高优先级线程的调度。

 

4.需要在等待条件变量线程被唤醒后,检测条件
(1)被拦截的唤醒:等待条件变量被唤醒并加锁相关互斥量,若一个其他线程获得了互斥量,它可能在等待之前先检查条件。由于条件为真,所以它不需等待,直接处理工作,当它解锁时,已经没有可做的工作了。我们的第一个等待条件变量线程加锁互斥量后,再次检测条件,很有必要。
(2)松散的条件:使用不确定的条件时,循环检测条件,代码会更加健壮。
(3)假唤醒:在某些多处理器系统,会发生假唤醒的情况。

 

5.使用示例

主线程等待条件信号2S,子线程睡眠1S,改变共享数据值,发送信号,主线程接收信号,继续运行。

#include<stdio.h>
#include<pthread.h>
#include<errno.h>                                                                
typedef struct cond_tag
{
        pthread_mutex_t mutex;
        pthread_cond_t cond;
        int valid;
}cond_t;
cond_t data = {
        PTHREAD_MUTEX_INITIALIZER,
        PTHREAD_COND_INITIALIZER,
        0
};
void *thread_route(void *arg)
{
        sleep(1);
        pthread_mutex_lock(&data.mutex);
        data.valid = 1;
        pthread_cond_signal(&data.cond);
        pthread_mutex_unlock(&data.mutex);
        return NULL;
}
int main(void)
{
        int status;
        pthread_t pid;
        pthread_create(&pid,NULL,thread_route,NULL);
        struct timespec timeout;
        timeout.tv_sec = time(NULL)+2;
        timeout.tv_nsec = 0;
        pthread_mutex_lock(&data.mutex);
        while(data.valid==0)
        {
                status = pthread_cond_timedwait(&data.cond,&data.mutex,&timeout);
                if(status==ETIMEDOUT)
                {
                        printf("wait timed out\n");
                        break;
                }
        }
        if(data.valid==1)
        {
                printf("cond is signaled\n");
        }
        pthread_mutex_unlock(&data.mutex);
        
        return 0;
}  

 

参考资料:《POSIX多线程程序设计》 pp.59-74

posted on 2016-04-13 11:16  迪米特  阅读(545)  评论(0编辑  收藏  举报

导航