linux网络编程-posix条件变量(40)
Posted luzhouxiaoshuai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux网络编程-posix条件变量(40)相关的知识,希望对你有一定的参考价值。
举一个列子来说明条件变量:
假设有两个线程同时访问全局变量n,初始化值是0,
一个线程进入临界区,进行互斥操作,线程当n大于0的时候才执行下面的操作,如果n不大于0,该线程就一直等待。
另外一个线程也是进入临界区,修改n的值,当修改了n的值后,需要向等待中的线程发送通知,修改了n的值。但是现在存在这样的一个问题:当第一个线程进入临界区的时候,第一个线程一直处在等待n改变的状态,第二个线程是无法进入临界区的修改n的值的,这样第一个线程
就处于死锁了。上面这个问题可以时候条件变量来解决。
条件变量也可以用于生产者和消费者的状态:
假设一个线程访问一个队列该队列是空的,那么该线程只能处于阻塞状态,直到其他线程将一个产品添加到队列中,发现通知通知等待的线程
对于等待条件的代码,首先需要锁定互斥量,因为这个条件变量是多个线程都可以同时访问的,所以需要进行互斥,这里使用while 等待只要条件为假,该线程就一直处于等待状态
对于给条件发现信号的代码:首先也是需要进行互斥,然后设置条件为真,然后给等待的线程发一个通知
下面我们使用条件变量来进行生产者与消费者的问题
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
pthread_cond_init函数可以用来初始化一个条件变量。他使用变量attr所指定的属性来初始化一个条件变量,如果参数attr为空,那么它将使用缺省的属性来设置所指定的条件变量。
pthread_cond_destroy函数可以用来摧毁所指定的条件变量,同时将会释放所给它分配的资源。调用该函数的进程也并不要求等待在参数所指定的条件变量上。
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
cond 条件变量
mutex 互斥锁
第一个参数*cond是指向一个条件变量的指针。第二个参数*mutex则是对相关的互斥锁的指针。
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
参数*cond是对类型为pthread_cond_t 的一个条件变量的指针。当调用pthread_cond_signal时一个在相同条件变量上阻塞的线程将被解锁。如果同时有多个线程阻塞,则由调度策略确定接收通知的线程。如果调用pthread_cond_broadcast,则将通知阻塞在这个条件变量上的所有线程。一旦被唤醒,线程仍然会要求互斥锁。如果当前没有线程等待通知,则上面两种调用实际上成为一个空操作。如果参数*cond指向非法地址,则返回值EINVAL。
#include <unistd.h> #include <sys/types.h> #include <pthread.h> #include <semaphore.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #define ERR_EXIT(m) \\ do \\ { \\ perror(m); \\ exit(EXIT_FAILURE); \\ } while(0) #define CONSUMERS_COUNT 1 #define PRODUCERS_COUNT 1 #define BUFFSIZE 10 //首先定义一个条件变量 pthread_cond_t g_cond; unsigned short in = 0; unsigned short out = 0; unsigned short produce_id = 0; unsigned short consume_id = 0; int nReady = 0;//表示当前产生的数目的计数器 pthread_mutex_t g_mutex; pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT]; void *consume(void *arg) { int i; int num = (int)arg; while (1) { // 首先需要进行互斥 pthread_mutex_lock(&g_mutex); while(nReady == 0){//等待产品不为空 //条件变量需要和互斥锁进行配合使用 printf("consume thread_id %d now is waiting for .....\\n",num); pthread_cond_wait(&g_cond,&g_mutex); } printf("consume thread_id %d now is begin consume product \\n",num); //消费产品,将产品数据减一 nReady = nReady -1; pthread_mutex_unlock(&g_mutex); sleep(1); } return NULL; } void *produce(void *arg) { int num = (int)arg; int i; while (1) { // 首先需要进行互斥 pthread_mutex_lock(&g_mutex); //开始生产产品 nReady = nReady +1; //发起通知 printf("producter thread_id %d now is singal for consume .....\\n",num); pthread_cond_signal(&g_cond); pthread_mutex_unlock(&g_mutex); sleep(3); } return NULL; } int main(void) { int i; //初始化一个互斥锁 pthread_mutex_init(&g_mutex, NULL); //初始化条件变量 pthread_cond_init(&g_cond,NULL); for (i = 0; i < CONSUMERS_COUNT; i++) pthread_create(&g_thread[i], NULL, consume, (void *)i); for (i = 0; i < PRODUCERS_COUNT; i++) pthread_create(&g_thread[CONSUMERS_COUNT + i], NULL, produce, (void *)i); for (i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; i++) pthread_join(g_thread[i], NULL); //销毁互斥锁 pthread_mutex_destroy(&g_mutex); //销毁条件变量 pthread_cond_destroy(&g_mutex); return 0; }
编译下代码:
gcc product.c -o product -lpthread
运行代码:
./product
代码中生产者和消费者都只有一个线程
我们来看程序运行的结果:
pthread_cond_wait前要先加锁
pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活
pthread_cond_wait被激活后会再自动加锁
pthread_cond_wait的内部实现流程:
1、第一步首先对互斥锁进行解锁
2、第二步等待其他线程改变条件变量
3、然后自动加锁后退出等待
以上是关于linux网络编程-posix条件变量(40)的主要内容,如果未能解决你的问题,请参考以下文章
C POSIX 线程的互斥体/条件的工作方式因变量所在的位置而异