生产者消费者模型
.多个线程操作全局变量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. 【Oracle 集群】Oracle 11G RAC教程之集群安装(七)

    Oracle 11G RAC集群安装(七) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总. ...

  2. 记一次nginx部署yii2项目时502 bad gateway错误的排查

    周六闲来无事,就试着安装和部署下yii2,安装过程没什么问题,但部署到nginx上时遇到了502 bad gatewary问题,折腾了半天才搞定.这个问题是我以前在部署yii2时没有遇到过的,因此记在 ...

  3. 网络爬虫:使用Scrapy框架编写一个抓取书籍信息的爬虫服务

      上周学习了BeautifulSoup的基础知识并用它完成了一个网络爬虫( 使用Beautiful Soup编写一个爬虫 系列随笔汇总 ), BeautifulSoup是一个非常流行的Python网 ...

  4. 在iOS中实现一个简单的画板App

    在这个随笔中,我们要为iPhone实现一个简单的画板App. 首先需要指出的是,这个demo中使用QuarzCore进行绘画,而不是OpenGL.这两个都可以实现类似的功能,区别是OpenGL更快,但 ...

  5. 浏览器加载和渲染HTML的过程(标准定义的过程以及现代浏览器的优化)

    先看一下标准定义的浏览器渲染过程(网上找的): 浏览器打开网页的过程 用户第一次访问网址,浏览器向服务器发出请求,服务器返回html文件: 浏览器开始载入html代码,发现 head 标签内有一个 l ...

  6. 如何在虚拟机安装桌面Ubuntu

    本篇仅为作业... 实验课程:Linux 实验机器:联想y410p 指导老师:刘臣奇 实验时间:2016年10月12日 学生学号:140815 姓名:杨文乾 一.新建一个虚拟机,按照之前建立虚拟机的步 ...

  7. Unmanaged Exports使用方法

    Unmanaged Exports,可以利用C#生成非托管的DLL文件. 从https://sites.google.com/site/robertgiesecke/下载UnmanagedExport ...

  8. 【转】zigbee终端无法重连的问题解决

    zigbee终端无法重连的问题解决 1.zigbee重连的原因 (1)zigbee由于各种原因的干扰导致信号太差而掉线. (2)协调器重启. 2.zigbee终端重连的处理 (1)zigbee掉线后会 ...

  9. Windows程序设计_19_测试Windows应用程序加载函数

    /* 本程序测试自定义的WinMainCRTStartup函数 */ #define STRICT #define WIN32_LEAN_AND_MEAN #include <windows.h ...

  10. HTTP协议下保证密码不被获取更健壮方式

    说到在http协议下用户登录如何保证密码安全这个问题:    小白可能第一想法就是,用户在登录页面输入密码进行登录时,前台页面对用户输入的密码进行加密,然后把加密后的密码作为http请求参数通过网络发 ...