精华内容
下载资源
问答
  • 生产者消费者模型(单个生产者和单个消费者)场景描述多线程开发中很经典的一个案例就是生产者消费者模型,它们共享资源,但是对资源的操作方式并不同。因此它们需要协调资源,否则就会出现线程安全问题。代码展示...

    生产者消费者模型(单个生产者和单个消费者)

    场景描述

    多线程开发中很经典的一个案例就是生产者消费者模型,它们共享资源,但是对资源的操作方式并不同。因此它们需要协调资源,否则就会出现线程安全问题。


    代码展示

    Resource Code

    /**
    * 生产者和消费者共享的资源Resource对象
    * @author xuyi3
    * @2016年4月7日 @下午2:01:21
    * @Resource
    * @功能说明:<br>
    * @春风十里不如你
    * @备注
    */
    public class Resource {
        /** 资源名称 */
        private String name;
        /** 资源标识符 */
        private boolean flag = false;
        //省略setter 和 getter 方法
    }
    

    ProductThread Code

    /**
    * 生产者线程
    * @author xuyi3
    * @2016年4月7日 @下午1:38:16
    * @ProductThread
    * @功能说明:生产产品<br>
    * @春风十里不如你
    * @备注
    */
    public class ProductThread implements Runnable {
        //共享资源Resource对象
        private Resource resource;
        public ProductThread(Resource resource) {
            this.resource = resource;
        }
    @Override
    public void run() {
        int count = 1;
        // 生产产品
        while (true) {
    
            synchronized (resource) {//共享资源对象(同步的锁要相同否则就错误)
                if (resource.isFlag()) {// 标识已经有资源
                    // wait();
                    try {
                        resource.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    // 生产资源
                    resource.setName("产品" + count);
                    System.out.println("生产者生产--->" + resource.getName());
                    count++;
                    resource.setFlag(true);
                    // notify();
                    resource.notify();
                }
            }
        }
    }
    }
    

    ConsumerThread Code

    /**
     * 消费者对象
     * @author xuyi3
     * @2016年4月7日 @下午2:07:22
     * @ConsumerThread
     * @功能说明:<br>
     * @春风十里不如你
     * @备注
     */
    public class ConsumerThread implements Runnable {
    
        // 共享资源Resource对象
        private Resource resource;
        public ConsumerThread(Resource resource) {
            this.resource = resource;
        }
        @Override
        public void run() {
    
            while (true) {
                synchronized (resource) {//共享资源对象(同步的锁要相同否则就错误)
                    if (!resource.isFlag()) {// 标识没有数据
                        // wait()
                        try {
                            resource.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        System.out.println("消费者消费===》" + resource.getName());
                        resource.setFlag(false);// 标识已经消费了
                        // notify()
                        resource.notify();
                    }
                }
            }
        }
    }
    

    AppMain Code

    public class AppMain {
    
    public static void main(String[] args) {
            // 共享资源对象
            Resource resource = new Resource();
            // 创建生产者对象
            ProductThread productThread = new ProductThread(resource);
            // 创建消费者对象
            ConsumerThread consumerThread = new ConsumerThread(resource);
    
            // 启动两个线程
            new Thread(productThread).start();
            new Thread(consumerThread).start();
        }
    }
    

    总结说明

    单个生产者和单个消费者模型实现的关键在于,资源共享(同步同个对象锁)和资源的标识以及等待唤醒机制wait()和notify()方法。

    展开全文
  • 生产者消费者问题 C++实现

    万次阅读 多人点赞 2018-06-29 17:00:03
    生产者消费者问题 C++实现 知识准备 thread 介绍 成员类 成员函数 sleep_for 介绍 mutex 介绍 成员函数 unique_lock 介绍 成员函数 codition_variable 介绍 成员函数 代码示例 生产者消费者问题 ...

    生产者消费者问题 C++实现

    知识准备

    thread

    介绍

    • 定位于头文件的class thread
    • 表示单个执行线程, 没有两个thread对象会表示同一个线程
      • 不可复制构造
      • 不可复制赋值

    成员类

    成员函数

    • get_id

      • 返回线程的id
    • hardware_concurrency

      • 返回实现支持的并发线程数
    • join

      • 等待线程完成其执行

    sleep_for

    介绍

    • 定义域头文件

    • 声明

      • template< class Rep, class Period >
        void sleep_for( const std::chrono::duration<Rep, Period>& sleep_duration );
        
      • sleep_duration : 要睡眠的时长

    mutex

    介绍

    • 定义于头文件

    • mutex 提供排他性非递归所有权语义:

      • 调用方线程从它成功调用 locktry_lock 开始,到它调用 unlock 为止占有 mutex
      • 线程占有 mutex 时,所有其他线程若试图要求 mutex 的所有权,则将阻塞(对于 lock 的调用)或收到 false 返回值(对于 try_lock ).
      • 调用方线程在调用 locktry_lock 前必须不占有 mutex

    成员函数

    • lock

      • 锁定互斥, 若互斥不可用则堵塞
    • unlock

      • 解锁互斥

    unique_lock

    介绍

    • 定义于

    • 声明

      template< class Mutex >
      class unique_lock;
      

    成员函数

    • lock
      • 锁定关联互斥
    • unlock
      • 解锁关联互斥
    • mutex
      • 返回指向关联互斥的指针

    codition_variable

    介绍

    • 定义于头文件 <condition_variable>
    • 声明class condition_variable;
    • 有意修改变量的线程必须:
        1. 获得std:: mutex(通过std::unique_lock)
        2. 在保有锁时进行修改
        3. 执行 notify_onenotify_all
    • 任何有意在 std::condition_variable 上等待的线程必须
        1. 获得std::unique_lock <std::mutex>
        2. 执行 waitwait_forwait_until ,等待操作自动释放互斥,并悬挂线程的执行
        3. 线程被唤醒,且自动重获得互斥
    • **std::condition_variable只可与 std::unique_lock<std::mutex>一同使用;

    成员函数

    • notify_one

      • 通知一个等待线程
    • notify_all

      • 通知所有等待线程
    • wait

      • 阻塞当前进程, 直至被唤醒
    • wait_for

      • 阻塞当前线程,直到条件变量被唤醒,或到指定时限时长后
      • wait_until
        • 阻塞当前线程,直到条件变量被唤醒,或直到抵达指定时间点
          

    代码示例

    // operator_system.cpp: 定义控制台应用程序的入口点。
    //
     
    #include "stdafx.h"
    #include<iostream>
    #include <mutex>
    #include <condition_variable>
    #include <windows.h>
    #include <thread>
     
    using namespace std;
     
    static const int buffer_size = 10; // 缓存大小
    static const int item_total = 100; //总共要生产 item_total个item
     
    // 缓存结构体, 使用循环队列当做缓存
    struct Buffer 
    {
    	int buffer[buffer_size];
    	size_t read_position; // 当前读位置
    	size_t write_position; // 当前写位置
    	mutex mtx; // 读写互斥
    	//条件变量
    	condition_variable not_full; 
    	condition_variable not_empty;
    }buffer_res;
     
    typedef struct Buffer Buffer;
     
    void porduce_item(Buffer *b, int item)
    {
    	unique_lock<mutex> lock(b->mtx);//设置互斥锁
     
    	while(((b->write_position + 1) % buffer_size) == b->read_position) {
    		//当前缓存已经满了
    		cout << "buffer is full now, producer is wating....." << endl;
    		(b->not_full).wait(lock); // 等待缓存非full
    	}
    	// 向缓存中添加item
    	(b->buffer)[b->write_position] = item;
    	(b->write_position)++;
     
    	// 若到达最后一个, 写位置置位0
    	if (b->write_position == buffer_size)
    		b->write_position = 0;
     
    	(b->not_empty).notify_all();
    	lock.unlock();
    }
     
    int consume_item(Buffer *b)
    {
    	int data;
    	unique_lock <mutex> lock(b->mtx);
    	while (b->write_position == b->read_position)
    	{	// 当前buffer 为空
    		cout << "buffer is empty , consumer is waiting....." << endl;
    		(b->not_empty).wait(lock);
    	}
     
    	data = (b->buffer)[b->read_position];
    	(b->read_position)++;
     
    	if (b->read_position >= buffer_size)
    		b->read_position = 0;
     
    	(b->not_full).notify_all();
    	lock.unlock();
     
    	return data;
    }
     
    //生产者任务
    void producer() {
    	for (int i = 1; i<= item_total;i++) {
    		cout << "prodece the " << i << "^th item ..." << endl;
    		porduce_item(&buffer_res, i);
    	}
    }
     
    //消费者任务
    void consumer()
    {
    	static int cnt = 0;
    	while(1) {
    		Sleep(1);
    		int item = consume_item(&buffer_res);
    		cout << "consume the " << item << "^th item" << endl;
    		if (++cnt == item_total)
    			break;
    	}
    }
     
    //初始化 buffer
    void init_buffer(Buffer *b)
    {
    	b->write_position = 0;
    	b->read_position = 0;
    }
     
    int main()
    {
    	init_buffer(&buffer_res);
    	thread prodece(producer);
    	thread consume(consumer);
    	prodece.join();
    	consume.join();
    	getchar();
    }
     
    

    查看其他精彩文章
    深入分析HashMap
    AOP核心原理和SpringAOP
    10分钟入门SpringAOP

    展开全文
  • #include #include #include ... // 创建生产者线程. std::thread consumer(consumer_task); // 创建消费之线程. producer.join(); consumer.join(); system("pause"); return 0; } 循环队列示意图:
    #include<iostream>
    #include<thread>
    #include<string>
    #include<mutex>
    #include<deque>
    #include<condition_variable>
    #include <windows.h>
    using namespace std;
    const int NUM = 50;   //循环队列大小,实际为49个,另外牺牲一个空间防止判断队列满的时候出现判断错误(假溢出)。
    struct DATA
    {
    	int num;
    };
    struct node {
    	DATA data[NUM];	
    	int tail;
    	int front;
    	int count;   //记录队列长度
    	condition_variable is_not_full; //条件变量不为满
    	condition_variable is_not_empty;//条件变量不为空
    	mutex mu;//互斥量保护数据空间防止竞争
    }NODE;
    typedef struct node node;
    bool isFull(node *q) { //判断队列是否为满
    
    	if ((q->tail+1)%NUM== q->front)
    		return true;
    	else
    		return false;
    }
    
    bool isEmpty(node *q) {  //判断队列是否为空
    
    	if (q->front == q->tail)
    		return true;
    	else
    		return false;
    }
    int Length(node *q)
    {
    
    	return (q->tail - q->front + NUM) % NUM;
    
    }
    void produce(node *q,int data) {
    	unique_lock<mutex> locker(q->mu);
    	while (isFull(q))//不为满就生产
    	{
    		cout << "队列已经满了,等待消费信号" << endl;
    		q->is_not_full.wait(locker);//等到不为满的条件到来,到来后就往队列里面填充元素
    	}
    	q->count += 1;
    	q->data[q->tail].num = data;
    	q->tail = (q->tail + 1) % NUM;
    	cout << "生产项目:" << data << endl;
    	q->is_not_empty.notify_all();//通知消费
    	locker.unlock();
    }
    
    int consumer(node *q)
    {
    	int data;
    	unique_lock<mutex> locker(q->mu);
    	while (isEmpty(q))//不为空就消耗
    	{
    		cout << "队列空了,等待生产信号" << endl;
    		q->is_not_empty.wait(locker);//到来后就是消耗元素,一直阻塞在这里
    	}
    	data = q->data[q->front].num;
    	q->front = (q->front + 1) % NUM;
    	q->count = q->count - 1;
    	q->is_not_full.notify_all();//通知生产
    	locker.unlock();
    	cout << "消费了:" <<data << endl;
    	return data;
    }
    
    void produce_task() {
    		for (int i = 1;; i++) //单个无限生产
    		{
    			produce(&NODE, i);
    }
    void consumer_task() {    //单个消费
    	int data;
    	Sleep(1);
    	while (1)
    	{
    		data = consumer(&NODE);
    
    	}
    
    }
    
    
    void myque_init(node *q)//队列初始化
    {
    	q->count = 0;
    	q->front = 0;
    	q->tail = 0;
    	for (int i = 0; i < NUM; i++)
    		q->data[i].num = 0;
    }
    
    
    
    int main()
    {
    	myque_init(&NODE);
    	std::thread producer(produce_task); // 创建生产者线程.
    	std::thread consumer(consumer_task); // 创建消费之线程.
    	producer.join();
    	consumer.join();
    	system("pause");
    	return 0;
    }
    循环队列示意图:

    展开全文
  • 单个生产者和单个消费者模型(spsc)

    千次阅读 2013-02-12 23:34:09
    while (spsc_queue.pop(value)) //生产者停工 ++consumer_count; } int main(int argc, char* argv[]) { using namespace std; cout ; if (!spsc_queue.is_lock_free()) cout ; cout ; boost::thread ...
    // LockFree.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    #include <boost/thread/thread.hpp>
    #include <boost/lockfree/spsc_queue.hpp>
    #include <iostream>
    
    #include <boost/atomic.hpp>
    
    	int producer_count = 0;
    boost::atomic_int consumer_count (0);
    
    boost::lockfree::spsc_queue<int, boost::lockfree::capacity<1024> > spsc_queue;
    
    const int iterations = 10000000;
    
    void producer(void)
    {
    	int count = 0;
    	for (int i = 0; i != iterations; ++i) {
    		int value = ++producer_count;
    		while (!spsc_queue.push(value)) //队列满则等待。
    			++count;
    	}
    	std::cout << "full " << count << " times\n";
    }
    
    boost::atomic<bool> done (false);
    
    void consumer(void)
    {
    	int value;
    	while (!done) { //生产者还在生产
    		while (spsc_queue.pop(value)) //如果有产品就消费
    			++consumer_count;
    	}
    
    	while (spsc_queue.pop(value)) //生产者停工
    		++consumer_count;
    }
    
    int main(int argc, char* argv[])
    {
    	using namespace std;
    	cout << "boost::lockfree::queue is ";
    	if (!spsc_queue.is_lock_free())
    		cout << "not ";
    	cout << "lockfree" << endl;
    
    	boost::thread producer_thread(producer);
    	boost::thread consumer_thread(consumer);
    
    	producer_thread.join();
    	done = true;
    	consumer_thread.join();
    
    	cout << "produced " << producer_count << " objects." << endl;
    	cout << "consumed " << consumer_count << " objects." << endl;
    }
    

    展开全文
  • 生产者-消费者问题

    千次阅读 2018-03-28 19:04:43
    问题基本描述生产者消费者问题是一个著名的进程同步的问题。它描述的是:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个...
  •  在第一节说到了生产者消费者问题,这一节我们来实现这样一个稍作修改的模型: 初始时缓冲区为空,生产者向缓冲区写入数据,消费者在缓冲区为空的情况下睡眠,当生产者写满缓冲区一半之后后通知消费者可以开始消费...
  • 生产者消费者问题详解

    千次阅读 2017-02-17 19:25:18
    定义生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者...
  • 秒杀多线程第十篇 生产者消费者问题

    万次阅读 多人点赞 2012-05-21 10:18:09
    继经典线程同步问题之后,我们来看看生产者消费者问题及读者写者问题。生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和...
  • 生产者消费者问题(代码实现)

    千次阅读 2016-07-19 22:29:29
    生产者-消费者问题(也被称为有界缓冲器问题)是一个典型的例子多线程同步的问题。问题描述了两个进程,生产者和消费者,谁都有一个共同的,固定大小的缓冲区作为一个队列。制片人的工作是生成数据,把它放入缓冲区...
  • // 消费者等待"产品库缓冲区不为空"这一条件发生. } data = q->data[q->front].num; q->front = (q->front + 1) % NUM; q->is_not_full.notify_all();//通知生产 cout () 消费了:" ; locker2.unlock(); ...
  • 生产者消费者问题 多个生产者和多个生产者的问题。生产者不断的向仓库放入产品,消费者不断的从仓库取出产品,仓库的容量是有限的。因此,当仓库处于满状态时,生产者必须等待消费者取出 1 个或多个产品后才能继续...
  • 生产者消费者模型

    千次阅读 多人点赞 2017-02-20 23:33:26
    一、什么是生产者消费者模型 在实际的开发中,经常会碰到如下场景:某个模块负责生产数据,这些数据由另一个模块来负责处理。产生数据的模块就形象的称为生产者,而处理数据的模块就称为消费者。只有生产者和消费...
  • 线程同步-生产者消费者问题

    万次阅读 2016-05-09 21:26:53
    在进行多线程编程时,难免还要碰到两个问题,那就线程间的互斥与同步: 线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才...
  • Linux进程间通信与生产者消费者问题

    千次阅读 2013-01-20 20:43:48
    生产者消费者问题(英语:Producer-consumerproblem),也称有限缓冲问题(英语:Bounded-bufferproblem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和...
  • 2、多生产者多消费者单缓冲区:不仅要考虑生产者消费者之间的互斥,为了避免多个生产者生产的产品放到缓冲区中的同一个位置、多个消费者消费同一个产品,还要考虑生产者之间、消费者之间的互斥关系。 3、多生产者多...
  • 又想到了操作系统里的消费者生产者模式,写了个小例子加深理解。 共享资源为Food类 代码如下: public class Food { private int count;//生产者消费者共享的资源 public Food() { } public ...
  • 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类: (1)采用某种机制...
  • 以下是在下对多线程中的单生产者,但消费者单个缓冲区问题的理解,Win32实现,如有不对之处还望大神指教,在下感激不尽!话休絮烦,用代码说话: #include&amp;lt;stdio.h&amp;gt; #include&...
  • 1、生产者-消费者问题(一)生产者-消费者问题是个经典的同步问题,也称为有界缓冲区问题,生产者、消费者代表某个线程或进程,生产者负责生产数据,消费者则对这些数据进行处理,数据是共享的,当有多个生产者或...
  • 【JAVA多线程】如何解决一个生产者消费者问题

    万次阅读 多人点赞 2018-11-01 15:28:19
    如何解决一个生产者消费者问题 生产者消费者问题是多线程同步的一个经典问题。生产者和消费者同时使用一块缓冲区,生产者生产商品放入缓冲区,消费者从缓冲区中取出商品。我们需要保证的是,当缓冲区满时,生产...
  • 生产者消费者问题产生的条件 条件:生产者线程Pp和消费者线程Pc同步,各Pp(Pc)间互斥。 互斥:可以简单理解为,某一公共资源不允许两个及以上并发线程同时访问。 同步:因并发线程各自的执行结果互为对方执行...
  • 操作系统:生产者消费者问题

    千次阅读 2016-06-06 12:16:13
    单个生产者,多个消费者,多个缓冲池,利用多线程通过同步互斥原则完成数据的读取。 解决方案: 生产者与消费者之间涉及同步问题,当缓冲池中有数据时,消费者才能去读取数据;当缓冲池有空余位置时,生产者才能去投...
  • 大部分人在理解Java的多线程这个问题有点困难,尤其是一些刚开始接触的编程语言是C语言...采用的例子:生产者消费者问题。 SyncStack存储WoTou Producer生产WoTou Consumer消费WoTou package com.exampl
  • 一、生产者-消费者问题 问题描述: 一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区 只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待 只有缓冲区不为空,消费者才能从中取出产品...
  • Java多线程技术~生产者消费者问题

    万次阅读 热门讨论 2020-06-16 14:15:18
    Java多线程技术~生产者消费者问题 本文是上一篇文章的后续,详情点击该连接 线程通信 应用场景:生产者消费者问题        假设仓库中只能存放一件产品,生产者将生产出来的...
  • 生产者消费者问题VC实现

    千次阅读 2013-10-25 20:41:10
    生产者消费者问题VC实现 一、实验任务 1、在WINDOWS 2000环境下,创建一个控制台进程,此进程包括2个线程:生产者线程和消费者线程。 2、用信号量机制解决进程(线程)的同步与互斥问题。 二、实验目的 1.掌握基本的...
  • 生产者消费者问题代码示例

    千次阅读 2017-07-14 20:48:24
    生产者消费者问题是一个经典的并发实例,因为项目需要代码优化实现程序并行,因此直接学习这一部分知识拿来用作代码的优化,也是边学习边理解。程序菜鸟一只,只希望尽快入门,早点得道。 这段代码是从别人处偷来的...
  • 文章目录生产者消费者问题描述PV操作题目分析步骤多生产者、多消费者问题描述问题分析吸烟者问题描述问题分析 生产者消费者问题描述 系统中有一组生产者进程和一组消费者进程,生产者进程每次生成一个产品放入...
  • 生产者/消费者模式的理解及实现

    万次阅读 多人点赞 2018-05-31 10:05:37
    ★简介 生产者消费者模式并不是GOF提出的23种设计模式之一,23种设计模式都是建立在面向对象的基础之上的,但其实面向过程的编程中也有很多高效的编程模式,生产者消费者模式便是其中之一,它是我们编程过程中最...
  • PV操作-单缓冲区生产者消费者问题 开始学操作系统,这个地方难住了,缓冲区也就是相当于市场。 S1=1,市场中的产品 S2=0,生产出来的产品 生产者: 生产者生产一个产品; P(S1); 送产品到缓冲区 V(S2); 消费者: P(S2)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,369
精华内容 18,147
关键字:

单个生产者消费者问题