生产者消费者模型已经很古老了吧,最近写了个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. Oracle RAC环境下定位并杀掉最终阻塞的会话-续

    之前在<Oracle RAC环境下定位并杀掉最终阻塞的会话>中,最终使用一个SQL查询出RAC实例之间的所有阻塞关系.但是实际在某些极端的生产环境,是不允许执行复杂的SQL语句,即使允许执 ...

  2. [NOIp 2016]天天爱跑步

    Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图 ...

  3. 【Codeforces Round #430 (Div. 2) A C D三个题】

    ·不论难度,A,C,D自己都有收获! [A. Kirill And The Game] ·全是英文题,述大意:    给出两组区间端点:l,r,x,y和一个k.(都是正整数,保证区间不为空),询问是否 ...

  4. ubuntu 安装 WPS for Linux(ubuntu)字体配置(字体缺失解决办法)及卸载libreoffice

    从官网下载安装wps for Linux sudo dpkg -i wps-office_10.1.0.5672~a21_amd64.deb 启动WPS for Linux后,出现提示"系统 ...

  5. VS2012代码对齐快捷键

    1.选中想要对齐的代码 2.全选代码后按住Ctrl+K,Ctrl+F键,就可以了

  6. 记录一次widora sdk编译ipk 实战编译redis

      因为业务需求,需要用到redis存储一点简单的数据,因为redis有良好的哈希机制,可以完美实现我的某些需求,但openwrt官方提供memcached的ipk并没有提供redis,没办法,只能自 ...

  7. java.sql.SQLException: **** [SQLServer]对象名 "XXXX"无效

    原因:进到数据库里面,但是没有选择数据库. 方法:检查数据源配置,这玩意容易看出.难得是多数据库操作时,切换数据源!

  8. linux route 路由设置小记

    情景一: 有一台ip为172.16.160.53服务器,此服务器为固定ip,由于某些特殊情况,此服务器的ip不能修改. 现在这台服务器需要与另外一个网段ip为172.16.176.150服务器进行局域 ...

  9. Docker学习系列(一)Docker简介

    简介 Docker是一个在全球范围领先的软件容器平台.开发人员可以使用容器来在协作过程中遇到的解决"不同环境配置"的问题.(例如,在传统的开发环境下,开发人员编写代码,然后交由测试 ...

  10. ubuntu14.04 python2.7 安装配置OpenCV3.0

    环境:ubuntu14.04  python2.7 内容:安装并配置OpenCV3.0 今天按照OpenCV官网上的步骤装了OpenCV但是,装好之后python提示“No module named ...