生产者消费者模型已经很古老了吧,最近写了个OpenMP版的此模型之实现,来分享下。

先说一下模型的大致做法是:

1、生产者需要取任务,生产产品。

2、消费者需要取产品,消费产品。

生产者在生产某个产品之后,要告知消费者此产品已经可以使用了。消费者通过获得可以使用这个信号来取得产品,进一步消费产品。

比如,我们有N个图像需要对每一个图像作滤波或者变换等处理,并且把处理后的结果存到硬盘上。

那么生产者可以将N个图像看成N个任务,每个任务都是独立的,每个任务的计算结果可以看成是产品,消费者就是取这个产品来写入硬盘。

先贴出一个实例代码再作解释。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

#define jobs 1000
#define sz 102000

#if defined(_WIN32) && defined(_MSC_VER)
#include <windows.h>
double abtic() {
	__int64 freq;
	__int64 clock;
	QueryPerformanceFrequency( (LARGE_INTEGER *)&freq );
	QueryPerformanceCounter( (LARGE_INTEGER *)&clock );
	return (double)clock/freq*1000*1000;
}
#else
#include <time.h>
#include <sys/time.h>
double abtic() {
	double result = 0.0;
	struct timeval tv;
	gettimeofday( &tv, NULL );
	result = tv.tv_sec*1000*1000 + tv.tv_usec;
	return result;
}
#endif /* _WIN32 */

#if 1
double timer;
#define ABTMS timer=abtic();fprintf(stdout,"%4d  ",__LINE__)
#define ABTME fprintf(stdout,"%4d  %8.8fms\n",__LINE__,(abtic()-timer)/1000.0f)
#else
#define ABTMS
#define ABTME
#endif

int main()
{
  char *jbNotReady;
  double *a;
  double *as;
  double *pa;
  int j, k;
	char jbnr;

  a = (double*)malloc(sz*jobs*sizeof(double));
  as = (double*)malloc(jobs*sizeof(double));
  jbNotReady = (char*)malloc(jobs*sizeof(char));

  for (j = 0; j < jobs; j++)
  {
    jbNotReady[j] = 1;

  }
  memset(a, 0, sz*jobs*sizeof(double));
  memset(as, 0, jobs*sizeof(double));
  ABTMS;
#pragma omp parallel sections private(j,k,pa) shared(jbNotReady,as,a)
  {
    // producer
#pragma omp section
    {
      for (j = 0; j < jobs; j++)
      {
        pa = a+j*sz;
        for (k = 0; k < sz; k++)
        {
          pa[k] = 1.0;
        }
        jbNotReady[j] = 0;
#pragma omp flush
      }
    }
    // consumer
#pragma omp section
    {
      for (j = 0; j < jobs; j++)
      {
#pragma omp flush
        while (jbNotReady[j]){
#pragma omp flush
				}
        as[j] = 0.0;
        pa = a+j*sz;
        for (k = 0; k < sz; k++)
        {
          as[j] += pa[k];
        }
        if ((int)(as[j])!=sz)fprintf(stdout, "job id %3d :%f\n", j, as[j]);
      }
    }
  }
  ABTME;
  free(a);
  free(as);
  free(jbNotReady);
  return 0;
}

源代码中,第一个section创建的线程扮演的就是生产者的角色,第二个section扮演消费者角色。j这个变量模拟的是任务编号,第一个section中的循环模拟产生产品。第二个section每次取一个任务,而且是顺序取,通过验证任务是否已经准备好来获得正确的产品。

使用flush制导语句是为了将每个线程的缓存和内存强制保持一致,注意生产者向jbNotReady里写,而消费者只是读数据,不会出现内存中的数据写后读,读后写的问题,每个线程获得的数据都是安全的。

以上代码支持Windows和Linux,GCC4.4以后的版本都可以执行,Windows下只要支持OpenMP的编译器,都可行。

OpenMP实现生产者消费者模型的更多相关文章

  1. 【Windows】用信号量实现生产者-消费者模型

    线程并发的生产者-消费者模型: 1.两个进程对同一个内存资源进行操作,一个是生产者,一个是消费者. 2.生产者往共享内存资源填充数据,如果区域满,则等待消费者消费数据. 3.消费者从共享内存资源取数据 ...

  2. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  3. Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)

    生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...

  4. Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

  5. Java多线程14:生产者/消费者模型

    什么是生产者/消费者模型 一种重要的模型,基于等待/通知机制.生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点: ...

  6. Java生产者消费者模型

    在Java中线程同步的经典案例,不同线程对同一个对象同时进行多线程操作,为了保持线程安全,数据结果要是我们期望的结果. 生产者-消费者模型可以很好的解释这个现象:对于公共数据data,初始值为0,多个 ...

  7. python_way ,day11 线程,怎么写一个多线程?,队列,生产者消费者模型,线程锁,缓存(memcache,redis)

    python11 1.多线程原理 2.怎么写一个多线程? 3.队列 4.生产者消费者模型 5.线程锁 6.缓存 memcache redis 多线程原理 def f1(arg) print(arg) ...

  8. 如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

    wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...

  9. Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

    Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...

随机推荐

  1. 使用Keras对交通标志进行分类

    # 使用Keras对交通标志进行分类 一.概述 本文主要记录的在使用Keras过程中,实现交通标志分类,数据集使用的是. 文本主要使用的环境为: Python3.5.2 Tensorflow 1.7 ...

  2. bzoj 4547 小奇的集合

    Description 有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大 值.(数据保证这个值为非负数) Input 第一行有两个整数n ...

  3. 冰精冻西瓜[P3787洛谷]

    题目描述 琪露诺是拥有操纵冷气程度的能力的妖精,一天她发现了一片西瓜地.这里有n个西瓜,由n-1条西瓜蔓连接,形成一个有根树,琪露诺想要把它们冷冻起来慢慢吃. 这些西瓜蔓具有神奇的性质,可以将经过它的 ...

  4. [Apio2009]Atm

    题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...

  5. Trie模版

    struct Trie{ Trie* nxt[]; int v; Trie(){ ;i<;i++){ nxt[i]=NULL; } v=-; } void insert(char s[],int ...

  6. 洛谷P2388 阶乘之乘

    题目背景 不告诉你-- 题目描述 求出1!*2!*3!*4!*--*n!的末尾有几个零 输入输出格式 输入格式: n(n<=10^8) 输出格式: 有几个零 输入输出样例 输入样例#1: 复制 ...

  7. poj 2689 (素数二次筛选)

    Sample Input 2 17 14 17 Sample Output 2,3 are closest, 7,11 are most distant. There are no adjacent ...

  8. FZU 2157 树形DP

    最开始一直不理解题是什么意思 ╯▽╰ 题意:给出n个点,每个点都有两种花费,一个是0种花费,一个是1种花费,每两个点相连,边也有花费,是随着点所取话费的种类不同,边的花费也不同,边有四种花费,00,0 ...

  9. LCT模板(BZOJ2631)

    用LCT实现路径加,路径乘,断开及加上一条边(保证是树),查询路径和. #include <cstdio> #include <algorithm> #define l(x) ...

  10. 在QEMU中调试ARM程序【转】

    转自:http://linuxeden.com/html/develop/20100820/104409.html 最近我想调试一个运行在QEMU模拟ARM系统中的Linux程序.我碰到过一些麻烦,因 ...