Linux系统编程之条件变量

Linux条件变量

  • 1. 头文件
  • 2. 类型
    • 2.1. 类型值
    • 2.2. 条件变量和属性类型
  • 3. 接口
    • 3.1. 条件变量接口
      • 3.1.1 动态初始化资源
      • 3.1.2. 动态释放资源
      • 3.1.3. 条件变量阻塞
      • 3.1.4. 带超时时间的条件变量阻塞
      • 3.1.5. 唤醒单个阻塞线程
      • 3.1.6. 唤醒所有被阻塞的线程
    • 3.2. 条件变量属性接口
      • 3.2.1. 属性初始化
      • 3.2.2. 属性释放
      • 3.2.3. 修改属性
      • 3.2.4. 查询属性
      • 3.2.5. 获取设置超时时间所用的时钟ID
      • 3.2.6. 设置超时时间所用的时钟ID
  • 4. 示例
    • 4.1. 条件变量示例

1. 头文件

#include

2. 类型

2.1. 类型值

//条件变量属性
enum
{
  	//线程属性默认值,表示条件变量在当前线程所在进程中的所有线程所共享
	PTHREAD_PROCESS_PRIVATE,  
	//表示条件变量可以在系统中跨进程共享
	PTHREAD_PROCESS_SHARED, 
};

2.2. 条件变量和属性类型

//定义一个条件变量,并使用静态方式进行初始化,必须定义和初始化放在一条语句中。
pthread_cond_t  tmpCond1 = PTHREAD_COND_INITIALIZER;

//定义条件变量后续使用动态方式初始化
pthread_cond_t tmpCond2;

//创建互斥锁属性
pthread_condattr_t tmpCondattr;

3. 接口

3.1. 条件变量接口

3.1.1 动态初始化资源

/*
 * 函数名称:pthread_cond_init
 * 功能:动态初始化条件变量资源
 * 参数:
 * 		__cond: 指向条件变量对象地址
 * 		__cond_attr:指向条件变量属性对象的地址
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_cond_init (pthread_cond_t *__restrict __cond, const pthread_condattr_t *__restrict __cond_attr);

3.1.2. 动态释放资源

/*
 * 函数名称:pthread_cond_destroy
 * 功能:动态释放条件变量资源
 * 参数:
 * 		__cond: 指向待释放的条件变量对象地址
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_cond_destroy (pthread_cond_t *__cond);

3.1.3. 条件变量阻塞

/*
 * 函数名称:pthread_cond_wait
 * 功能:调用此接口使线程阻塞,直到条件变量满足条件后返回
 * 参数:
 * 		__cond:指向等待满足条件的条件变量地址
 * 		__mutex: 指向和条件变量配合使用的互斥锁对象
 * 返回值:0--成功,其他错误码-失败
*/
int pthread_cond_wait (pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex);

3.1.4. 带超时时间的条件变量阻塞

/*
 * 函数名称:pthread_cond_timedwait
 * 功能:调用此接口使线程阻塞,直到条件变量满足条件后返回或达到设置的超时时间后返回
 * 参数:
 * 		__cond:指向等待满足条件的条件变量地址
 * 		__mutex: 指向和条件变量配合使用的互斥锁对象
 * 		__abstime:指向设置的超时时间的绝对时间的结构体地址,即需要获取当前系统时间加上超时时间,而不是直接设置一个超时值。
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex, const struct timespec *__restrict __abstime);

3.1.5. 唤醒单个阻塞线程

/*
 * 函数名称:pthread_cond_signal
 * 功能:唤醒一个被阻塞的线程
 * 参数:
 * 		__cond: 指向待唤醒条件变量对象地址
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_cond_signal (pthread_cond_t *__cond);

3.1.6. 唤醒所有被阻塞的线程

/*
 * 函数名称:pthread_cond_broadcast
 * 功能:唤醒所有被阻塞的线程
 * 参数:
 * 		__cond: 指向待唤醒的条件变量对象地址
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_cond_broadcast (pthread_cond_t *__cond);

3.2. 条件变量属性接口

3.2.1. 属性初始化

/*
 * 函数名称:pthread_condattr_init
 * 功能:初始化条件变量属性资源
 * 参数:
 * 		__attr: 指向待初始化的条件变量属性对象地址
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_condattr_init (pthread_condattr_t *__attr);

3.2.2. 属性释放

/*
 * 函数名称:pthread_condattr_destroy
 * 功能:释放条件变量属性资源
 * 参数:
 * 		__attr: 指向待释放条件变量属性对象地址
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_condattr_destroy (pthread_condattr_t *__attr);

3.2.3. 修改属性

/*
 * 函数名称:pthread_condattr_setpshared
 * 功能:设置当前条件变量属性值
 * 参数:
 * 		__attr: 指向条件变量属性对象地址
 * 		__pshared:要设置的线程属性PTHREAD_PROCESS_PRIVATE或PTHREAD_PROCESS_SHARED
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_condattr_setpshared (pthread_condattr_t *__attr, int __pshared);

3.2.4. 查询属性

/*
 * 函数名称:pthread_condattr_getpshared
 * 功能:获取当前条件变量属性值
 * 参数:
 * 		__attr: 指向条件变量属性对象地址
 * 		__pshared:指向获取的线程属性的地址,线程属性为PTHREAD_PROCESS_PRIVATE或PTHREAD_PROCESS_SHARED
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_condattr_getpshared (pthread_condattr_t *__attr, 					int *__restrict __pshared);

3.2.5. 获取设置超时时间所用的时钟ID

/*
 * 函数名称:pthread_condattr_getclock
 * 功能:获取设置超时时间所用的时钟ID
 * 参数:
 * 		__attr: 指向互斥锁健壮属性对象地址
 * 		__clock_id:指向用来保存时钟ID的地址
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_condattr_getclock (const pthread_condattr_t * __restrict __attr, __clockid_t *__restrict __clock_id);

3.2.6. 设置超时时间所用的时钟ID

/*
 * 函数名称:pthread_condattr_setclock
 * 功能:修改设置超时时间所用的时钟ID
 * 参数:
 * 		__attr: 指向互斥锁健壮属性对象地址
 * 		__clock_id:要设置的时钟ID值
 * 返回值:0--成功,其他错误码--失败
*/
int pthread_condattr_setclock (pthread_condattr_t *__attr, __clockid_t __clock_id);

4. 示例

4.1. 条件变量示例

#include 
#include 
#include 
#include 
#include 

//定义全局条件变量
pthread_cond_t g_cond;
//定义全局条件变量属性
pthread_condattr_t g_condattr;
//定义结合全局条件变量使用的互斥锁
pthread_mutex_t g_mutex;

int g_iValue = 0;

//动态初始化条件变量
void init_cond()
{
    pthread_condattr_init(&g_condattr);

    pthread_cond_init(&g_cond, &g_condattr);

    pthread_mutex_init(&g_mutex, nullptr);
}

//释放条件变量资源
void destroy_cond()
{
    pthread_condattr_destroy(&g_condattr);

    pthread_cond_destroy(&g_cond);

    pthread_mutex_destroy(&g_mutex);
}

//阻塞线程,直到条件变量满足
static void* condWaitThread(void *arg)
{
    std::cout << "start condWaitThread." << std::endl;
    
    //在阻塞现场前需要先加锁
    pthread_mutex_lock(&g_mutex);
    pthread_cond_wait(&g_cond, &g_mutex);
    std::cout << "continue condWaitThread." << std::endl;
    g_iValue += 1;
    std::cout << "g_iValue is " << g_iValue << std::endl;
    pthread_mutex_unlock(&g_mutex);
    
    std::cout << "over condWaitThread." << std::endl;

    return nullptr;
}

//阻塞线程,直到条件变量满足或者达到设置的超时时间
static void* condTimewaitThread(void *arg)
{
    std::cout << "start condTimewaitThread." << std::endl;

    //获取系统时间
    struct timespec struTimeout = {0};
    struct timespec struCurrTime = {0};
    clock_gettime(CLOCK_REALTIME, &struCurrTime);

    //超时时间设置为5s
    struTimeout.tv_sec = struCurrTime.tv_sec + 5;
    struTimeout.tv_nsec = struCurrTime.tv_nsec;

    //在阻塞现场前需要先加锁
    pthread_mutex_lock(&g_mutex);
    int iret = pthread_cond_timedwait(&g_cond, &g_mutex, &struTimeout);
    if (0 == iret)
    {
        std::cout << "weak up continue condTimewaitThread." << std::endl;
    }
    else
    {
        std::cout << "timeout continue condTimewaitThread." << std::endl;
    }
    
    g_iValue += 1;
    std::cout << "g_iValue is " << g_iValue << std::endl;
    pthread_mutex_unlock(&g_mutex);

    std::cout << "over condTimewaitThread." << std::endl;

    return nullptr;
}

int main()
{
    //初始化
    init_cond();

    pthread_t threadWait, threadTimewait;

    //创建wait线程
    pthread_create(&threadWait, nullptr, condWaitThread, nullptr);
    pthread_detach(threadWait);

    //创建带超时时间的线程
    pthread_create(&threadTimewait, nullptr, condTimewaitThread, nullptr);
    pthread_detach(threadTimewait);

    sleep(1);
    //唤醒单个线程,此处唤醒的线程是随机的
    pthread_cond_signal(&g_cond);
    
    //唤醒所有线程,当signal新唤醒的是condWaitThread时,
    //修改次数延时时间会影响condTimewaitThread的返回结果。
    sleep(5);
    pthread_cond_broadcast(&g_cond);

    //释放资源
    destroy_cond();

    return 0;
}

你可能感兴趣的:(Linux系统编程,linux)