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() #define CONSUMERS_COUNT 1
#define PRODUCERS_COUNT 1
#define BUFFSIZE 10 //首先定义一个条件变量
pthread_cond_t g_cond; unsigned short in = ;
unsigned short out = ;
unsigned short produce_id = ;
unsigned short consume_id = ;
int nReady = ;//表示当前产生的数目的计数器
pthread_mutex_t g_mutex; pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT]; void *consume(void *arg)
{
int i;
int num = (int)arg;
while ()
{
// 首先需要进行互斥
pthread_mutex_lock(&g_mutex);
while(nReady == ){//等待产品不为空
//条件变量需要和互斥锁进行配合使用
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 -;
pthread_mutex_unlock(&g_mutex);
sleep(); }
return NULL;
} void *produce(void *arg)
{
int num = (int)arg;
int i;
while ()
{
// 首先需要进行互斥
pthread_mutex_lock(&g_mutex);
//开始生产产品
nReady = nReady +;
//发起通知
printf("producter thread_id %d now is singal for consume .....\n",num);
pthread_cond_signal(&g_cond);
pthread_mutex_unlock(&g_mutex);
sleep();
}
return NULL;
} int main(void)
{
int i; //初始化一个互斥锁
pthread_mutex_init(&g_mutex, NULL);
//初始化条件变量
pthread_cond_init(&g_cond,NULL); for (i = ; i < CONSUMERS_COUNT; i++)
pthread_create(&g_thread[i], NULL, consume, (void *)i); for (i = ; i < PRODUCERS_COUNT; i++)
pthread_create(&g_thread[CONSUMERS_COUNT + i], NULL, produce, (void *)i); for (i = ; i < CONSUMERS_COUNT + PRODUCERS_COUNT; i++)
pthread_join(g_thread[i], NULL); //销毁互斥锁
pthread_mutex_destroy(&g_mutex);
//销毁条件变量
pthread_cond_destroy(&g_mutex); return ;
}
编译下代码:
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)的更多相关文章
- Linux多线程编程的条件变量
在stackoverflow上看到一关于多线程条件变量的问题,题主问道:什么时候会用到条件变量,mutex还不够吗?有个叫slowjelj的人做了很好的回答,我再看这个哥们其他话题的一些回答,感觉水平 ...
- Linux 多线程编程—使用条件变量实现循环打印
编写一个程序,开启3个线程,这3个线程的ID分别为A.B.C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示:如:ABCABC….依次递推. 使用条件变量来实现: #inc ...
- linux网络编程-posix信号量与互斥锁(39)
-posix信号量信号量 是打开一个有名的信号量 sem_init是打开一个无名的信号量,无名信号量的销毁用sem_destroy sem_wait和sem_post是对信号量进行pv操作,既可以使用 ...
- linux网络编程之posix条件变量
今天来学习posix的最后一个相关知识----条件变量,言归正传. 下面用一个图来进一步描述条件变量的作用: 为什么呢? 这实际上可以解决生产者与消费者问题,而且对于缓冲区是无界的是一种比较理解的解决 ...
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_co ...
- Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题
前面的一片文章我们已经讲过使用信号量解决生产者消费者问题.那么什么情况下我们须要引入条件变量呢? 这里借用 http://www.cnblogs.com/ngnetboy/p/3521547.htm ...
- Linux网络编程入门 (转载)
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- [转] - Linux网络编程 -- 网络知识介绍
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- 【转】Linux网络编程入门
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
随机推荐
- 【图机器学习】cs224w Lecture 13 & 14 - 影响力最大化 & 爆发检测
目录 Influence Maximization Propagation Models Linear Threshold Model Independent Cascade Model Greedy ...
- 数据库原理实验指导(三)使用SQL语言进行简单查询【转载csdn】
--1.查询全体学生的学号和姓名select sno,sname from student --2.查询全体学生的详细记录select * from student --3.查询软件学院的学生姓名,年 ...
- 基于S7-PLCSIM Advanced搭建S7通信仿真环境
写在前面: 之前有专门讲过一期如何搭建西门子PLC的S7通信仿真环境,感兴趣的可以点击查看:戳↓ 1.基于TIA搭建西门子PLC仿真环境及通信方案-联合出品 2.手把手教你搭建西门子PLC仿真环境 那 ...
- Web-从Java Request对象到HTTP协议
https://mp.weixin.qq.com/s/PjcA22STEDGwRxVQweObQQ Java Web中的Request对象是哪里来的?Response对象的角色是什么? Java We ...
- (String),toString(),String.valueOf()
String.valueOf("")的源码:(推荐这种写法) 注意:obj问null时,返回值是字符串"null" toString("") ...
- 实战| 配置DataDog监控Apache Hudi应用指标
1. 可用性 在Hudi最新master分支,由Hudi活跃贡献者Raymond Xu贡献了DataDog监控Hudi应用指标,该功能将在0.6.0 版本发布,也感谢Raymond的投稿. 2. 简介 ...
- Liunx下使用wine容器实现跨平台使用软件
首先在Liunx中使用QQ,网易云音乐,等这些软件是很痛苦的,某些软件可能会有Liunx版本,但是像腾讯QQ早年前也提供过Linux版本,后来就下架了!!! 这里我以ubuntu18.04版本为列,讲 ...
- ActiveMQ 笔记(四)Spring\SpringBoot 整合 Activemq
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.Spring 整合Activemq 1.所需jar包 <dependencies> &l ...
- Java实现蓝桥杯 算法训练 Professor Monotonic's Network
试题 算法训练 Professor Monotonic's Network 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 无聊的教授最近在做一项关于比较网络的实验.一个比较网络由若 ...
- Java实现 洛谷 P1009 阶乘之和
import java.util.Scanner; public class 阶乘之和 { public static void main(String[] args) { Scanner sc = ...