生产者消费者模型
.多个线程操作全局变量n,需要做成临界区(要加锁--线程锁或者信号量)
.调用函数pthread_cond_wait(&g_cond,&g_mutex)让这个线程锁在某一个条件上等待
--pthread_cond_wait()函数的本质是①:拿到锁的线程,把锁暂时丢掉(解锁)②:线程休眠,进行等待③:线程等待通知,醒来继续执行(重新获得锁)
--这个pthread_cond_wait()函数是一个原子性操作
--注意:丢掉的锁可以被生产线程获得,也可以被消费线程获得,消费者线程获取会陷入等待,生产者线程获得会发送信号,唤醒消费者
.pthread_cond_signal()生产者拿到锁,生产n,生产完成后,发送信号给消费者(唤醒消费者),生产者离开临界区
//生产者消费者模型
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h> //定义线程锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//定义线程条件锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//定义全局变量
int g_num = ; //定义消费者线程数量
#define Consume_Count 2 //定义生产者线程数量
#define Product_Count 4 //消费者线程
void *consume_run(void * arg)
{
int tnum = (int) arg;
while ()
{
//因为多线程操作一个全局变量,需要做成临界区,枷锁
pthread_mutex_lock(&mutex);
printf("消费者%d进入临界区!\n", tnum);
//因为就算消费者被唤醒,也需要重新检查g_num的值,因为pthread_cond_wait()函数丢锁之后,可能被其他消费者获得
//导致多个消费者线程都执行了pthread_cond_wait()函数陷入等待,
//因为多个消费者线程被pthread_cond_signal()唤醒,但是资源只有一个,可能已经被其他消费者使用了
//pthread_cond_wait()也有可能被其他信号唤醒
//所以需要重新判断,而不能使用if
while (g_num == )
{
printf("消费者%d开始等待!\n", tnum);
//在该线程锁上,进行条件等待
pthread_cond_wait(&cond, &mutex);
printf("消费者%d被唤醒!\n", tnum);
}
//表示已经有资源了,可以消费了
printf("消费者%d开始消费!\n", tnum);
g_num--;
//解锁
pthread_mutex_unlock(&mutex);
sleep();
}
return NULL;
} //生产者线程
void *product_run(void * arg)
{
int tnum = (int) arg;
while ()
{
//当生产者大于消费者时,可能出现生产过多的商品,需要对商品的上限做一个限制,如果商品过多,需要让生产者睡眠
//涉及到对全局变量的访问,需要加锁
printf("现有资源个数%d!\n",g_num);
pthread_mutex_lock(&mutex);
if (g_num > )
{
printf("生产者%d产品已经到达上限,进入睡眠!\n", tnum);
//如果生产产品大于上限,需要睡眠,但是睡眠前应该将锁释放.,留给消费者进行消费
pthread_mutex_unlock(&mutex);
sleep();
continue;
} else
{
printf("生产者%d生产产品!\n", tnum);
//如果生产产品小于上限,那么不需要生产者睡眠,接着生产产品
g_num++;
//发送条件信号
printf("生产者%d发送条件信号!\n", tnum);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
pthread_mutex_unlock(&mutex);
sleep();
}
return NULL;
} int main(int arg, char * args[])
{
pthread_t thrs[Consume_Count + Product_Count];
int i = ;
for (i = ; i < Consume_Count; i++)
{
if (pthread_create(&thrs[i], NULL, consume_run, (void *) i) != )
{
printf("pthread_create() failed !\n");
return -;
}
}
for (i = ; i < Product_Count; i++)
{
if (pthread_create(&thrs[i + Consume_Count], NULL, product_run,
(void *) i) != )
{
printf("pthread_create() failed !\n");
return -;
}
}
//join
for (i = ; i < Consume_Count + Product_Count; i++)
{
if (pthread_join(thrs[i], NULL) != )
{
printf("pthread_join() failed !\n");
break;
}
}
printf("进程推出了!\n");
return ;
}

Linux Posix线程条件变量的更多相关文章

  1. Linux Qt使用POSIX多线程条件变量、互斥锁(量)

    今天团建,但是文章也要写.酒要喝好,文要写美,方为我辈程序员的全才之路.嘎嘎 之前一直在看POSIX的多线程编程,上个周末结合自己的理解,写了一个基于Qt的用条件变量同步线程的例子.故此来和大家一起分 ...

  2. python线程条件变量Condition(31)

    对于线程与线程之间的交互我们在前面的文章已经介绍了 python 互斥锁Lock / python事件Event , 今天继续介绍一种线程交互方式 – 线程条件变量Condition. 一.线程条件变 ...

  3. linux Posix线程同步(条件变量) 实例

    条件变量:与互斥量一起使用,暂时申请不到某资源时进入条件阻塞等待,当资源具备时线程恢复运行 应用场合:生产线程不断的生产资源,并通知产生资源的条件,消费线程在没有资源情况下进入条件等待,一直等到条件信 ...

  4. Linux 线程 条件变量

    一:条件变量 直接上最基本的两个函数,先抓主要矛盾: //等待条件 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex ...

  5. Linux posix线程库总结

    由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现. 线程的实现,经历了如下发展阶段: Linu ...

  6. linux多线程-互斥&条件变量与同步

    多线程代码问题描述 我们都知道,进程是操作系统对运行程序资源分配的基本单位,而线程是程序逻辑,调用的基本单位.在多线程的程序中,多个线程共享临界区资源,那么就会有问题: 比如 #include < ...

  7. posix多线程--条件变量

    条件变量是用来通知共享数据状态信息的. 1.条件变量初始化两种方式:(1)静态初始化pthread_cond_t cond = PTHREAD_COND_INITIALIZER;代码示例如下: #in ...

  8. Linux系统编程—条件变量

    条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用.条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等 ...

  9. linux TLS 线程本地变量

    最近在写底层hook的时候, 涉及到线程安全问题, 最开始我设计的时候使用的互斥量, 但是考虑到都是底层函数,加锁会导致性能问题, 一直在思考优化方案, 后来偶然想到,java里面有线程本地变量的AP ...

随机推荐

  1. ASP.NET Core 中文文档 第二章 指南(4.10)检查自动生成的Detail方法和Delete方法

    原文 Examining the Details and Delete methods 作者 Rick Anderson 翻译 谢炀(Kiler) 校对 许登洋(Seay).姚阿勇(Mr.Yao) 打 ...

  2. .Net语言 APP开发平台——Smobiler学习日志:如何实现离线声音文件上传

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的"S ...

  3. Android开机动画

    Android系统的开机动画可分为三个部分,kernel启动,init进程启动,android系统服务启动.这三个开机动画都是在一个叫做 帧缓冲区(frame buffer)的硬件设备上进行渲染绘制的 ...

  4. [连载]《C#通讯(串口和网络)框架的设计与实现》- 13.中英文版本切换设计

    目       录 第十三章     中英文版本切换设计... 2 13.1        不用自带的资源文件的理由... 2 13.2        配置文件... 2 13.3        语言 ...

  5. Eclipse搭建Maven Prooject(终于)

    今天我们一起来探讨eclipse搭建maven项目的步骤 一.建一个maven项目, 1.找到File ,点击 2.弹出窗口,再点击new 3.弹出窗口,点击other 4.输入maven,找到mav ...

  6. freemarker页面中文乱码

    一.前言 简单的记录freemarker遇到的错误问题:ftl页面中文乱码 由于freemarker整合在ssm框架中,所以笔者直接贴配置代码 <beans xmlns="http:/ ...

  7. iOS 汉字的拼音

    获取汉字的拼音 #import <Foundation/Foundation.h> @interface NSString (Utils) /** * 汉字的拼音 * * @return ...

  8. CentOS7 查看IP、Gateway、DNS、Hostname

    1.查看IP# ip addr 2.查看路由# ip route 3.查看DNS# cat /etc/resolv.conf 4.查看主机名# hostname

  9. 利用私有的库MobileCoreServices检测正在安装的应用

    利用的私有库检测正在安装的app 分为两步:第一,通过placeholderApplications获得所有的正在安装的app的信息 第二,遍历正在安装的app的信息,根据名称获得你想检测的app是否 ...

  10. iOS从零开始学习直播之音频1.播放本地音频文件

      现在直播越来越火,俨然已经成为了下一个红海.作为一个资深码农(我只喜欢这样称呼自己,不喜欢别人这样称呼我),我必须赶上时代的潮流,开始研究视频直播.发现视屏直播类的文章上来就讲拉流.推流.采集.美 ...