POSIX 条件变量

更新时间:
2024-05-29
下载文档

POSIX 条件变量

POSIX 条件变量的类型为 pthread_cond_t。使用时需要定义一个 pthread_cond_t 类型的变量,如:

pthread_cond_t cond;

POSIX 条件变量需要与 POSIX 互斥信号量结合使用,使用 POSIX 条件变量前,我们需要先创建一个用于共享资源锁用途的 POSIX 互斥信号量。

一个 POSIX 条件变量必须要调用 pthread_cond_init 函数初始化之后才能使用。

线程如果需要等待一个条件变量,可以调用 pthread_cond_wait 函数,中断服务程序不可以调用 pthread_cond_wait 函数等待一个条件变量,因为 pthread_cond_wait 函数会阻塞当前线程。

发送一个条件变量可以使用 pthread_cond_signal 或 pthread_cond_broadcast 函数,中断服务程序不可以发送一个 POSIX 条件变量。

当一个条件变量使用完毕后(并确保以后也不再使用),应该调用 pthread_cond_destroy 函数删除它,SylixOS 会回收该条件变量占用的内核资源。

创建一个 POSIX 条件变量需要使用 POSIX 条件变量属性块。POSIX 条件变量属性块的类型为 pthread_condattr_t。使用时需要定义一个 pthread_condattr_t 类型的变量,如:

pthread_condattr_t         condattr;

条件变量属性块

条件变量属性块的初始化和删除

#include <pthread.h>
int   pthread_condattr_init(pthread_condattr_t  *pcondattr);

函数 pthread_condattr_init 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcondattr 是 POSIX 条件变量属性块的指针。
#include <pthread.h>
int   pthread_condattr_destroy(pthread_condattr_t  *pcondattr);

函数 pthread_condattr_destroy 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcondattr 是 POSIX 条件变量属性块的指针。

设置和获取条件变量属性块的进程共享属性

#include <pthread.h>
int   pthread_condattr_setpshared(pthread_condattr_t  *pcondattr, 
                                  int                  ishare);

函数 pthread_condattr_setpshared 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcondattr 是 POSIX 条件变量属性块的指针。
  • 参数 ishare 标识了 POSIX 条件变量属性块是否进程共享。
#include <pthread.h>
int    pthread_condattr_getpshared(const pthread_condattr_t  *pcondattr, 
                                   int                       *pishare);

函数 pthread_condattr_getpshared 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcondattr 是 POSIX 条件变量属性块的指针。
  • 输出参数 pishare 标识了 POSIX 条件变量属性块是否进程共享。

设置和获取条件变量属性块的时钟类型

#include <pthread.h>
int    pthread_condattr_setclock(pthread_condattr_t  *pcondattr, 
                                 clockid_t            clock_id);

函数 pthread_condattr_setclock 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcondattr 是 POSIX 条件变量属性块的指针。
  • 参数 clock_id 是时钟类型。

注意:
当前参数 clock_id 只能用宏 CLOCK_REALTIME。

#include <pthread.h>
int  pthread_condattr_getclock(const pthread_condattr_t  *pcondattr, clockid_t  *pclock_id);

函数 pthread_condattr_getclock 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcondattr 是 POSIX 条件变量属性块的指针。
  • 输出参数 clock_id 是时钟类型。

条件变量

条件变量的初始化和删除

#include <pthread.h>
int    pthread_cond_init(pthread_cond_t            *pcond,
                         const pthread_condattr_t  *pcondattr);

函数 pthread_cond_init 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcond 是 POSIX 条件变量的指针。
  • 参数 pcondattr 是 POSIX 条件变量属性块的指针,可以为 NULL。
#include <pthread.h>
int    pthread_cond_destroy(pthread_cond_t  *pcond);

函数 pthread_cond_destroy 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 pcond 是 POSIX 条件变量的指针。

条件变量的发送

#include <pthread.h>
int    pthread_cond_signal(pthread_cond_t     *pcond);
int    pthread_cond_broadcast(pthread_cond_t  *pcond);

以上两个函数原型分析:

  • 函数成功返回 0,失败返回错误号。
  • 参数 pcond 是 POSIX 条件变量的指针。

pthread_cond_broadcast 与 pthread_cond_signal 函数的区别在于,pthread_cond_broadcast 会以广播的方式唤醒阻塞在该条件变量的所有线程,而 pthread_cond_signal 只会唤醒一个线程。

条件变量的等待

#include <pthread.h>
int    pthread_cond_wait(pthread_cond_t   *pcond,   
                         pthread_mutex_t  *pmutex);
int    pthread_cond_timedwait(pthread_cond_t          *pcond, 
                              pthread_mutex_t         *pmutex,
                              const struct timespec   *abs_timeout);
int    pthread_cond_reltimedwait_np(pthread_cond_t         *pcond, 
                                    pthread_mutex_t        *pmutex,
                                    const struct timespec  *rel_timeout);

以上三个函数原型分析:

  • 函数成功返回 0,失败返回错误号。
  • 参数 pcond 是 POSIX 条件变量的指针。
  • 参数 pmutex 是 POSIX 互斥信号量的指针。
  • 参数 abs_timeout 是等待的绝对超时时间。
  • 参数 rel_timeout 是等待的相对超时时间。

pthread_cond_timedwait 是 pthread_cond_wait 的带等待超时时间的版本,abs_timeout 为等待的绝对超时时间。

pthread_cond_reltimedwait_np 是 pthread_cond_timedwait 的非 POSIX 标准版本,参数 rel_timeout 为等待的相对超时时间。

下面程序展示了 POSIX 条件变量的使用,程序创建两个线程和一个 POSIX 互斥信号量及一个 POSIX 条件变量;线程 thread_a 对变量 count 打印,线程 thread_b 对变量 count 进行自增操作,使用 POSIX 互斥信号量作为访问变量 count 的互斥手段,使用 POSIX 条件变量作为变量 count 值改变的通知手段。

程序清单 POSIX条件变量的使用(POSIX_Conditional_Variable)

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

static pthread_mutex_t    lock;
static pthread_cond_t     cond;
static int                count = 0;

static void *thread_a (void *arg)
{
    while (1) {
        pthread_mutex_lock(&lock);
        pthread_cond_wait(&cond, &lock);
        printf("thread_a(): count = %d\n", count);
        pthread_mutex_unlock(&lock);
    }
    return  (NULL);
}

static void *thread_b (void *arg)
{
    while (1) {
        pthread_mutex_lock(&lock);
        count++;
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&lock);
        sleep(1);
    }
    return  (NULL);
}

int main (int argc, char *argv[])
{
    pthread_t  threada_tid;
    pthread_t  threadb_tid;
    int        ret;

    ret = pthread_mutex_init(&lock, NULL);
    if (ret != 0) {
        fprintf(stderr, "mutex create failed.\n");
        return  (-1);
    }
    ret = pthread_cond_init(&cond, NULL);
    if (ret != 0) {
        fprintf(stderr, "cond create failed.\n");
        return  (-1);
    }
    ret = pthread_create(&threada_tid, NULL, thread_a, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread create failed.\n");
        return  (-1);
    }
    ret = pthread_create(&threadb_tid, NULL, thread_b, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread create failed.\n");
        return  (-1);
    }
    pthread_join(threada_tid, NULL);
    pthread_join(threadb_tid, NULL);
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&lock);

    return  (0);
}

在 SylixOS Shell 下运行程序:

# ./POSIX_Conditional_Variable
thread_a(): count = 1
thread_a(): count = 2
thread_a(): count = 3
thread_a(): count = 4
thread_a(): count = 5
thread_a(): count = 6
......
# ts
          NAME                TID    PID  PRI STAT LOCK SAFE    DELAY   PAGEFAILS FPU CPU
--------------------------- ------- ----- --- ---- ---- ---- ---------- --------- --- ---
POSIX_Conditional_Variable  401006c    34 200 JOIN    0               0         1 USE   0
pthread                     401006d    34 200 SEM     0               0         0       0
pthread                     401006e    34 200 SLP     0             212         0       0
文档内容是否对您有所帮助?
有帮助
没帮助