3线程同步:条件变量

简介: 1条件变量 条件变量给多个线程提供了一个汇合的场所。 依赖的头文件 #include<pthread.h> 函数声明 定义分配条件变量 pthread_cond_t cond =PTHREAD_COND_INITIALIZER;   int pthread_cond_init(pthread_cond_t*restrict c

1条件变量

条件变量给多个线程提供了一个汇合的场所。

依赖的头文件

#include<pthread.h>

函数声明

定义分配条件变量

pthread_cond_t cond =PTHREAD_COND_INITIALIZER;

 

int pthread_cond_init(pthread_cond_t*restrict cond, const pthread_condattr_t *restrict attr);

名称:

pthread_cond_init

功能:

initialize condition variables  初始化条件变量

头文件:

#include <pthread.h>

函数原形:

int pthread_cond_init(pthread_cond_t *restrict cond,

             const pthread_condattr_t *restrict attr);

参数:

 

返回值:

the pthread_cond_destroy() and pthread_cond_init() functions shall return zero; otherwise, an error number shall be returned to indicate the error

 

int pthread_cond_destroy(pthread_cond_t*cond);

名称:

pthread_cond_destroy

功能:

Destroy condition variables  销毁条件变量

头文件:

#include <pthread.h>

函数原形:

int pthread_cond_destroy(pthread_cond_t *cond);

参数:

 

函数说明:

在释放或废弃条件变量之前,需要毁坏它,使用此函数

返回值:

the pthread_cond_destroy() and pthread_cond_init() functions shall return zero; otherwise, an error number shall be returned to indicate the error

 

int pthread_cond_wait(pthread_cond_t*restrict cond,pthread_mutex_t *restrict mutex);

名称:

pthread_cond_wait

功能:

Wait on a condition,等待某个条件是否成立。对于timewait()函数除了等待以外,可以设置一个时长。

头文件:

#include <pthread.h>

函数原形:

intpthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

参数:

 

函数说明:

一旦初始化了互斥对象和条件变量,就可以等待这个条件,一个特定条件只能有一个互斥对象,而且条件变量应该表示互斥数据“内部”的一种特殊的条件更改。一个互斥条件可以用许多条件变量(例如:cond_empty,cond_full,cond_cleanup,但每个条件变量只能有一个互斥对象。

返回值:

 

 

int pthread_cond_signal(pthread_cond_t*cond);

名称:

pthread_cond_signal

功能:

signal a condition,这种情况是只有一个线程收到后执行动作。

头文件:

#include <pthread.h>

函数原形:

int pthread_cond_signal(pthread_cond_t *cond);

参数:

 

函数说明:

活动线程只需要唤醒第一个正在睡眠的线程。假设您只对队列添加了一个工作作业。那么只需要唤醒一个工作程序线程(再唤醒其它线程是不礼貌的!)

返回值:

 

 

int pthread_cond_broadcast(pthread_cond_t*cond);

名称:

pthread_cond_broadcast

功能:

broadcast a condition,通过广播的形式发给子线程消息,子线程竞争执行。

头文件:

#include <pthread.h>

函数原形:

int pthread_cond_broadcast(pthread_cond_t *cond);

参数:

 

函数说明:

如果线程更改某些共享数据,而且它想要唤醒所有正在等待的线程,则应使用 pthread_cond_broadcast调用

返回值:

 

案例说明:

#include <stdlib.h>

#include <pthread.h>

#include <stdio.h>

#include <unistd.h>

 

struct msg {

   struct msg *next;

   int num;

};

 

struct msg *head;

/*条件变量 */

pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void *consumer(void *p)

{

   struct msg *mp;

   for (;;) {

       pthread_mutex_lock(&lock);

       /* pthread_cond_wait(&has_product, &lock);

        * 1.阻塞等待has_product被唤醒,

        * 2.释放互斥锁, pthread_mutex_unlock(&lock)

        * 3.当被唤醒时,解除阻塞,并且重新去申请获得互斥锁 pthread_mutex_lock(&lock)

        */

       while (head == NULL)

           pthread_cond_wait(&has_product, &lock);

 

       mp = head;

       head = mp->next;

       pthread_mutex_unlock(&lock);

       printf("Consume %d\n", mp->num);

       free(mp);

       sleep(rand() % 5);

   }

}

 

void *producer(void *p)

{

   struct msg *mp;

   for (;;) {

       mp = (struct msg *)malloc(sizeof(struct msg));

       mp->num = rand() % 1000 + 1;

       printf("Produce %d\n", mp->num);

       pthread_mutex_lock(&lock);

       mp->next = head;

       head = mp;

       pthread_mutex_unlock(&lock);

       /* pthread_cond_broadcast(&has_product)唤醒等待队列上的所有线程*/

                  //发送信号,告诉消费者有产品了

       pthread_cond_signal(&has_product);

       sleep(rand() % 5);

   }

}

 

int main(int argc, char *argv[])

{

   pthread_t pid, cid;

   srand(time(NULL));

   pthread_create(&pid, NULL, producer, NULL);

   pthread_create(&cid, NULL, consumer, NULL);

   pthread_join(pid, NULL);

   pthread_join(cid, NULL);

   return 0;

}

运行结果:

总结:从上面可以看出,消费者总是消费最先生产出来的一个。

目录
相关文章
|
1月前
|
存储 Java 测试技术
ThreadLocal:线程专属的变量
ThreadLocal:线程专属的变量
41 0
|
7月前
|
Java 调度
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(3)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(3)
|
7月前
|
Java 应用服务中间件 容器
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(4)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(4)
|
7月前
|
Java 应用服务中间件
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(5)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(5)
|
7月前
|
Java 物联网 应用服务中间件
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(6)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(6)
|
7月前
|
缓存 算法 Java
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(7)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(7)
|
7月前
|
Java 数据库连接
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(9)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(9)
|
7月前
|
Java
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)
|
7月前
|
Java
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(11)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(11)
|
6月前
|
程序员 调度
多线程的创建,复习匿名内部类,Thread的一些方法,以及lambda的变量捕捉,join用法(二)
多线程的创建,复习匿名内部类,Thread的一些方法,以及lambda的变量捕捉,join用法