#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define BUFFER_SIZE 21 //初始化存储空间的大小
#define END_FLAG (-1)//用于退出循环
struct Products
{
int buffer[BUFFER_SIZE];//存储空间
pthread_mutex_t locker; //声明互斥变量
pthread_cond_t notEmpty;//声明条件变量
pthread_cond_t notFull;
int posReadFrom;
int posWriteTo;
};
int flag1=,flag2=,num1=,num2=;//变量一定要记得初始化,很重要,前两个为了标记,后两个为了计数
struct Products products; //定义结构体变量,下面要用到的
int BufferIsFull(struct Products* products)//如果满,则返回1,否则返回0;
{
if ((products->posWriteTo + )%BUFFER_SIZE==products->posReadFrom)
{
return ();
}
return ();
} int BufferIsEmpty(struct Products* products)//如果空,则返回1,否则返回0;
{
if ((products->posWriteTo)==(products->posReadFrom))
{
return ();
} return ();
} /*制造产品*/
void Produce(struct Products* products, int item)
{
/*原子操作*/
pthread_mutex_lock(&products->locker);
/*无空间可写入*/
while (BufferIsFull(products))
{flag1=;//标记变量
pthread_cond_wait(&products->notFull, &products->locker);
}
/*写入数据*/
products->buffer[products->posWriteTo] = item;
products->posWriteTo++;
pthread_mutex_unlock(&products->locker);//在解锁之后发射信号
/*发信*/
if(flag2==)
{flag2=;//这行代码至关重要,一开始我就是忘了写,然后会不断输出这句
pthread_cond_signal(&products->notEmpty);
printf("Produce调用了唤醒函数%d次\n",++num1);//检查代码的执行情况是否正确,因为加入这行代码,更容易分析
} } int Consume(struct Products* products)
{
int item; pthread_mutex_lock(&products->locker);
/*为空时持续等待,无数据可读*/
while (BufferIsEmpty(products))
{flag2=;
pthread_cond_wait(&products->notEmpty, &products->locker);
}
/*提取数据*/
item = products->buffer[products->posReadFrom];
products->posReadFrom++;
pthread_mutex_unlock(&products->locker);
if(flag1==)
{flag1=;pthread_cond_signal(&products->notFull);
printf("Consume调用了唤醒函数%d次\n",++num2);} return item;
}
void* ProducerThread(void* data)
{
int i;
for (i = ; i <; ++i)
{
printf("producer: %d\n", i);
Produce(&products, i);
}
Produce(&products, END_FLAG);
return NULL;
} void* ConsumerThread(void* data)
{
int item; while ()
{
item = Consume(&products);
if (END_FLAG == item)
break;
printf("consumer: %d\n", item);
}
return (NULL);
}
int main(int argc, char* argv[])
{
pthread_t producer;
pthread_t consumer;
int result;
pthread_create(&producer, NULL, &ProducerThread, NULL);
pthread_create(&consumer, NULL, &ConsumerThread, NULL);
pthread_join(producer, (void *)&result);
pthread_join(consumer, (void *)&result);
printf("products.posReadFrom=%d\n",products.posReadFrom);//测试循环次数
printf("products.posWriteTo=%d",products.posWriteTo);
exit(EXIT_SUCCESS);
}
//pthread_cond_signal此处我用了if进行判断,因为如果不进行判断,
//则每次都会执行这句,信号发出去了,但是没人接收!(这个思想很重要的)
/*为什么这个结构体变量没有初始化,反而它的两个数据成员,一开始都为0,
真的让我不知道为啥,最后我终于明白了原来因为这个程序中把struct Products结构体变量,
products声明为全局变量所以系统自动初始化了!这方面的只是好久不看都忘了!*/

pthread_cond_wait和pthread_cond_signal以及互斥变量的使用情况的更多相关文章

  1. 关于 pthread_cond_wait 和 pthread_cond_signal , signal 无效的问题

    关于一个消费者模式,,,引起的问题.. 我在io线程里不断的把一个函数调用放到队列里 然后ruby线程就不断的从这个队列里取出函数之争并运行. 典型的 消费者模式. 我曾经以为是这样... 这是wor ...

  2. 条件变量pthread_cond_wait()和pthread_cond_signal()详解

    条件变量        条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起:另一个线程使"条件成立" ...

  3. 深入理解pthread_cond_wait、pthread_cond_signal

    ===============================man pthread_cond_wait的解释========================== LINUX环境下多线程编程肯定会遇到 ...

  4. 面试题:如何在不使用临时变量temp的情况下交换两个整数的值?

    利用一个小技巧,一个整数a在异或另一个整数b两次以后所得的值还是整数a. 具体的过程我们可以自己找两个整数以二进制的形式自己在纸上画一下他们的异或过程.(异或的运算符号为"^") ...

  5. 继承时,当父子类都具有相同的成员变量,默认情况下是直接调用子类的成员变量,当要调用父类的成员变量则需要使用super关键之

    package day02; public class Person { String name="fl"; }class Car{ }class Student extends ...

  6. 【mybatis】mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 或者 feign被调用方使用的mybatis总报空指针异常java.lang.NullPointerException,而变量都没有问题的情况

    mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 需要检查的步骤: ...

  7. 线程相关函数(6)-pthread_cond_wait(),pthread_cond_signal(), 条件变量

    pthread_cond_tpthread_cond_initpthread_cond_destroypthread_cond_waitpthread_cond_timedwaitpthread_co ...

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

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

  9. node源码详解(七) —— 文件异步io、线程池【互斥锁、条件变量、管道、事件对象】

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource7 本博客同步在https://cnodejs.o ...

随机推荐

  1. C#基础第二天-作业答案-九九乘法表-打印星星

    题一:九九乘法表的答案 //正三角 ; i < ; i++) { ; j <= i; j++) { Console.Write("{0}*{1}={2} ", j, i ...

  2. 3dmax,查看场景中所有材质

  3. centos 7 下图形验证码乱码

    工作中遇到一个问题:同样的代码在centos 6.5下图形验证码是正常的 但是在centos 7下面是乱码 centos 6.5 的系统字体库目录 [wwwad@P2P-test2 fonts]$ p ...

  4. Win7/Win8.1右键菜单技巧:应用程序任意加

    对于Win7.Win8.1老用户来说,日常使用中离不开双击各类第三方应用程序,尤其是常用的记事本.QQ聊天.关机.一键截图等程序,这时我们不妨将这些“右键菜单”,轻松实现一键开启QQ.截图或者关机等功 ...

  5. [na]wireshark排查打印机问题

    抓包工具排除故障 前言:上网慢,可能是内网堵了.装上wireshark,可抓到广播包,多播包,以及发给自己的包.如果想抓lan内其他人之间的通信包,那就要在sw上做端口镜像. 1.背景 调试打印机的人 ...

  6. Win7下使用无线网卡共享上网的4种方式

    我尝试了第一种直接上网了     一.Win7自带无线承载网络功能 1.查看网卡是否支持承载网络功能运行“命令提示符”   输入命令:netsh wlan show drivers图中红框“支持的承载 ...

  7. 【Unity】3.1 利用内置的3D对象创建三维模型

    分类:Unity.C#.VS2015 创建日期:2016-04-02 一.基本概念 Unity已经内置了一些基本的3D对象,利用这些内置的3D对象就可以直接构建出各种3D模型(当然,复杂的三维模型还需 ...

  8. HTML5学习笔记(十九):Lambda和Promise

    Lambda 在ES6的标准中称为Arrow Function(箭头函数).下面是一个简单的箭头函数: x => x * x 上面的定义和下面的代码定义效果一样: function (x) { ...

  9. 菜鸟学Java(六)——简单验证码生成(Java版)

    验证码大家都知道,它的作用也不用我多说了吧.如果不太清楚请参见百度百科中的解释,一般验证码的生成就是随机产生字符(数字.字母或者汉字等),然后将这些生成的字符绘制成一张图片,再在图片上加上一些干扰元素 ...

  10. redis中键空间通知

    通过redis的键空间通知,当redis删除过期key的时候,及时更新mongodb数据库中user的状态 var Redis = require('ioredis'); var redis = ne ...