精华内容
下载资源
问答
  • 生产者与消费者问题

    千次阅读 2010-08-02 18:21:00
    多线程编程中的一个典型问题是生产者与消费者问题,这是线程同步或者说是线程间通信的一个典型实例。这里再简单复习一下吧。 在这个问题中,有一个生产者负责源源不断地生成产品放入仓库,还一个消费者源源不断地从...

          多线程编程中的一个典型问题是生产者与消费者问题,这是线程同步或者说是线程间通信的一个典型实例。这里再简单复习一下吧。
          在这个问题中,有一个生产者负责源源不断地生成产品放入仓库,还一个消费者源源不断地从仓库中提出产品。仓库有一个固定的容量,仓库满的时候生产者的操作要暂时挂起等待仓库有空间时再放入产品,当仓库空的时候,消费者提取产品的工作也会挂起,等待仓库中有产品放入后再继续。因此说,存放产品和提取产品是两个需要同步的操作,或者准确地说:消费者的消费操作和生产者的生产操作是可以同步进行的(并发执行),但同时它们之间又必须通过一定的机制来相互的协调,在某些特殊的时刻,让谁先执行,谁后执行,才能避免出现上述问题。
          在java中,这个问题就是通过wait和notify来实现的。注意:wait和notify必须放在同步块中!一般情况是同步块的加锁对象就是wait和notify的从属对象。wait方法将释放当前对象的锁,这样当前线程就被置于block状态(因为当前线程在当前对象上是同步的),以便其他线程可以执行,直到它需要的某个条件由其他线程实现了。而notify方法正是那个实现了某个条件的线程用来通知虚拟机,可以尝试唤醒其他线程了。等到这个线程执行完毕,归还了当前对象的锁,某个被唤醒的线程会得到这个锁,比如说前一个wait的线程,这时候它们条件已经满足,因而可以继续执行下去了。
        
    wait和notify与同步机制的关系: “竞争条件”是指两个以上的线程会因为执行顺序的不同而导致程序变量或是返回值的不同。这样必然会出现错误的结果,这种错误的结果有一种叫法:共享数据的腐蚀。同步机制正是用来解决“竞争条件”问题的。但是仅有同步是不够的,本质上,同步是确保共享数据能被线程安全地访问, 它是从“ 隔离 线程”角度来安排线程的推进的。但是线程除了需要隔离,还需要相互通信,以协调地完成一项工作,这正是wait和notify的作用。以下是Java Theads一书的摘入:

         The wait-and-notify mechanism is a synchronization mechanism. However, it is more of a communication mechanism: it allows one thread to communicate to another thread that a particular condition has occurred. The wait-and-notify mechanism does not specify what the specific condition is.

         Can the wait-and-notify mechanism be used to replace the synchronized mechanism? Actually, the answer is no; wait-and-notify does not solve the race condition problem that the synchronized mechanism solves. As a matter of fact, wait-and-notify must be used in conjunction with the synchronized lock to prevent a race condition in the wait-and-notify mechanism itself.

     

    下面是生产者与消费者的代码:

    Store:仓库类

     

    Producer:生产者

    Consumer:消费者


    展开全文
  • 生产者与消费者问题C语言实现

    万次阅读 多人点赞 2018-05-27 10:51:24
    生产者消费者问题是典型的PV操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。缓冲池被占用时,...

    实验目的
    ①实现生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。生产者-消费者问题是典型的PV操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。缓冲池被占用时,任何进程都不能访问。

    ②每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。

    实验原理
    在同一个进程地址空间内执行两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。

    生产者流程图
    这里写图片描述
    消费者流程图
    这里写图片描述
    注意点
    ①本次实验是关于生产者与消费者之间互斥和同步的问题。问题的是指是P、V操作,实验设一个共享缓冲区,生产者和消费者互斥的使用,当一个线程使用缓冲区的时候,另一个让其等待直到前一个线程释放缓冲区为止。
    ②生产者与消费者是一个与现实有关的经验问题,通过此原理举一反三可以解决其他类似的问题。 通过本实验设计,我们对操作系统的P、V进一步的认识,深入的了解P、V操作的实质和其重要性。课本的理论知识进一步阐述了现实中的实际问题。
    ③Linux环境下编写变异C语言有Windows稍有不同,注意在Linux中编译带有线程

    #include <stdio.h>
    #include <pthread.h>
    #include <windows.h>
    #define N 100
    #define true 1
    #define producerNum  10
    #define consumerNum  5
    #define sleepTime 1000
    
    typedef int semaphore;
    typedef int item;
    item buffer[N] = {0};
    int in = 0;
    int out = 0;
    int proCount = 0;
    semaphore mutex = 1, empty = N, full = 0, proCmutex = 1;
    
    void * producer(void * a){
        while(true){
            while(proCmutex <= 0);
            proCmutex--;
            proCount++;
            printf("生产一个产品ID%d, 缓冲区位置为%d\n",proCount,in);
            proCmutex++;
    
            while(empty <= 0){
                printf("缓冲区已满!\n");
            }
            empty--;
    
            while(mutex <= 0);
            mutex--;
    
            buffer[in] = proCount;
            in = (in + 1) % N;
    
            mutex++;
            full++;
            Sleep(sleepTime);
        }
    }
    
    void * consumer(void *b){
        while(true){
            while(full <= 0){
                printf("缓冲区为空!\n");
            }
            full--;
    
            while(mutex <= 0);
            mutex--;
    
            int nextc = buffer[out];
            buffer[out] = 0;//消费完将缓冲区设置为0
    
            out = (out + 1) % N;
    
            mutex++;
            empty++;
    
            printf("\t\t\t\t消费一个产品ID%d,缓冲区位置为%d\n", nextc,out);
            Sleep(sleepTime);
        }
    }
    
    int main()
    {
        pthread_t threadPool[producerNum+consumerNum];
        int i;
        for(i = 0; i < producerNum; i++){
            pthread_t temp;
            if(pthread_create(&temp, NULL, producer, NULL) == -1){
                printf("ERROR, fail to create producer%d\n", i);
                exit(1);
            }
            threadPool[i] = temp;
        }//创建生产者进程放入线程池
    
    
        for(i = 0; i < consumerNum; i++){
            pthread_t temp;
            if(pthread_create(&temp, NULL, consumer, NULL) == -1){
                printf("ERROR, fail to create consumer%d\n", i);
                exit(1);
            }
            threadPool[i+producerNum] = temp;
        }//创建消费者进程放入线程池
    
    
        void * result;
        for(i = 0; i < producerNum+consumerNum; i++){
            if(pthread_join(threadPool[i], &result) == -1){
                printf("fail to recollect\n");
                exit(1);
            }
        }//运行线程池
        return 0;
    }

    这里写图片描述
    更多内容访问omegaxyz.com
    网站所有代码采用Apache 2.0授权
    网站文章采用知识共享许可协议BY-NC-SA4.0授权
    © 2018 • OmegaXYZ-版权所有 转载请注明出处

    展开全文
  • c++多线程生产者与消费者问题代码

    千次阅读 2017-03-14 10:43:47
    c++多线程生产者与消费者问题代码

    1.目录结构

    2.代码

    BufferPool.h

    #ifndef BUFFERPOOL
    #define BUFFERPOOL
    #include<windows.h>
    #include<vector>
    #include<iostream>
    #include<string>
    #define SIZE_OF_BUFFER 4
    using namespace std;
    //控制参数类
    class BufferPool
    {
    public:
    	static BufferPool * GetInstance();
    	
    	void Produce();
    	void Consume();
    	void Product_Sum();
    
    	//多线程互斥信号量
    	HANDLE mutex;
    	HANDLE mutex2;
    
    	//多线程同步信号量
    	//空缓冲区
    	HANDLE m_hSemaphoreBufferEmpty;
    	//非空缓冲区
    	HANDLE m_hSemaphoreBufferFull;
    
    	unsigned int produce_sum;            //the total produce number
    	unsigned int consume_sum;            //the total consume number
    
    private:
    
    	unsigned short in;                   //the mark of position entering the space 
    	unsigned short out;                  //the mark of position leaving the space
    	unsigned int Product_ID;
    	unsigned int Consume_ID;
    
    	static BufferPool *m_Instance;
    	int buffer[SIZE_OF_BUFFER];          //缓冲池
    
    	BufferPool()
    	{
    		int i = 0;
    		in = out = 0;
    		produce_sum = consume_sum = 0;
    		Product_ID = Consume_ID = 0;
    		for(;i < SIZE_OF_BUFFER; i++)
    			buffer[i] = 0;
    	
    	};
    
    };
    #endif
    Consume.h

    #ifndef CONSUME
    #define CONSUME
    #include "BufferPool.h"
    #include<windows.h>
    #include<vector>
    #include<iostream>
    #include<string>
    class Consume
    {
    public:
    Consume(){};
    ~Consume(){};
    //消费产品
    DWORD WINAPI ConsumeProduct(LPVOID lpParam);
    };
    #endif

    Product.h

    #ifndef PRODUCT
    #define PRODUCT
    #include "BufferPool.h"
    #include<windows.h>
    #include<vector>
    #include<iostream>
    #include<string>
    class Product
    {
    public:
    Product(){};
    ~Product(){};
    //消费产品
    DWORD WINAPI producer(LPVOID lpParam);
    };
    #endif

    BufferPool.cpp

    #include "BufferPool.h"
    
    //---------------------------------------------------------------------------
    
    //---------------------------------------------------------------------------
    //unsigned short in, out;
    //in = out = 0;
    //获取单例实例
    BufferPool * BufferPool::m_Instance = new BufferPool();
    
    BufferPool * BufferPool::GetInstance()
    {
    if(NULL == m_Instance)
    {
    m_Instance = new BufferPool();
    }
    return  m_Instance;
    }
    
    void BufferPool::Produce()
    {
     int i;
     std::cout<<"produce";
     //if(Product_ID>=10)
     // Product_ID=0;
     Product_ID++;
     produce_sum++;
     buffer[in]=Product_ID;
     printf(" buffer[%d]=%d    ",in,Product_ID);
     in=(in+1)%SIZE_OF_BUFFER;
        Product_Sum();
    }
    
    void BufferPool::Consume()
    {
     int i;
     std::cout<<"consume";
     consume_sum++;
     Consume_ID=buffer[out];
     printf(" buffer[%d]=%d    ",out,Consume_ID);
     buffer[out]=0;
     out=(out+1)%SIZE_OF_BUFFER;
     Product_Sum();
    }
    
    void BufferPool::Product_Sum()
    {
     int i,sum=0;
     for(i=0;i<SIZE_OF_BUFFER;i++)
     {
      if(buffer[i]!=0)
       sum++;
     }
    // std::cout<<"  "<<sum<<"         ";
     //for(i=0;i<SIZE_OF_BUFFER;i++)
     //{
     // std::cout<<buffer[i]<<" ";
     //}
     printf("   %d\n", sum);
    }
    

    consume.cpp

    #include "Consume.h"
    //---------------------------------------------------------------------------
    
    DWORD WINAPI Consume::ConsumeProduct(LPVOID lpParam)
    {
    	while (true)
    	{
    		//等待非空的缓冲区出现,消费者进行消费,直到事件值为0
    		WaitForSingleObject(BufferPool::GetInstance()->m_hSemaphoreBufferFull, INFINITE);
    		WaitForSingleObject(BufferPool::GetInstance()->mutex2,INFINITE);                //the mutex P operation
    		BufferPool::GetInstance()->Consume();
    		Sleep(1000);
    	    ReleaseMutex(BufferPool::GetInstance()->mutex2);                                //resource semaphore P operation
    		ReleaseSemaphore(BufferPool::GetInstance()->m_hSemaphoreBufferEmpty,1,NULL);            //the mutex P operation
    	}
    	return 0;
    }

    Main_prg.cpp

    #include<stdlib.h>
    #include<windows.h>
    #include "BufferPool.h"
    #include "Product.h"
    #include "Consume.h"
    
    typedef DWORD (WINAPI *pTheadFunc)(LPVOID lpParam);
    
    const unsigned short p_count=5;        //the number of produce one time
    const unsigned short c_count=5;        //the number of consumer one time
    const unsigned short s_count=p_count+c_count;  //the sum number of threads
    bool control = true;
    HANDLE threads[s_count];               //the handle of every thread
    DWORD Producer_threadID[p_count];            //the mark of producer thread
    DWORD Consumer_threadID[c_count];            //the mark of consumer thread
    
    void Create_P_Threads();
    void Create_C_Threads();
    
    void Create_P_Threads()                                  //create producer thread
    {
    	for(int i=0;i<p_count;i++)
    	{
    		 DWORD (WINAPI Product::*pProductPoint)(LPVOID lpParam) = &Product::producer;
    		 int* ptemp= (int*)&pProductPoint;
    		 DWORD (WINAPI *pProductThread)(LPVOID lpParam) = *(pTheadFunc*)ptemp;
    		 //生产者线程
    		 threads[i]=CreateThread(NULL,0,pProductThread,NULL,0,&Producer_threadID[i]);
    		 if(threads[i]==NULL)
    			control=false;
    	}
    }
    
    
    void Create_C_Threads()
    {
    	for(int i=p_count;i<s_count;i++)
    	{
    
    		DWORD (WINAPI Consume::*pConsumePoint)(LPVOID lpParam) = &Consume::ConsumeProduct;
    		int* ptemp= (int*)&pConsumePoint;
    		DWORD (WINAPI *pConsumeThread)(LPVOID lpParam) = *(pTheadFunc*)ptemp;
    		//消费者线程
    		threads[i]=CreateThread(NULL,0,pConsumeThread,NULL,0,&Consumer_threadID[i-p_count]);
    		if(threads[i]==NULL)
    			control=false;
    	 }
    }
    
    
    void info()
    {
    	std::cout<<"\n"<<std::endl;
    	std::cout<<"produce/consume    used_total  buffer_state(from 0 to 9)"<<std::endl;
    }
    
    
    int main()
    {
     info();
     BufferPool::GetInstance()->mutex=CreateMutex(NULL,FALSE,NULL);
     BufferPool::GetInstance()->mutex2=CreateMutex(NULL,FALSE,NULL);
     BufferPool::GetInstance()->m_hSemaphoreBufferFull=CreateSemaphore(NULL,0,SIZE_OF_BUFFER,NULL);
     BufferPool::GetInstance()->m_hSemaphoreBufferEmpty=CreateSemaphore(NULL,SIZE_OF_BUFFER,SIZE_OF_BUFFER,NULL);
     Create_C_Threads();
     Create_P_Threads();
     
    	 while(control)
    	 {
    		  if(getchar())
    		  {
    			   std::cout<<std::endl;
    			   std::cout<<"the total produce product number is "<<BufferPool::GetInstance()->produce_sum<<std::endl;
    			   std::cout<<"the total consume product number is "<<BufferPool::GetInstance()->consume_sum<<std::endl;
    			   break;
    		  }
    	 }
    	 return 0;
    }

    Product.cpp

    #include "Product.h"
    //---------------------------------------------------------------------------
    DWORD WINAPI  Product::producer(LPVOID lpParam)
    {
    	while (true)
    	{
    		//等待非空的缓冲区出现,消费者进行消费,直到信号量值为0
    		WaitForSingleObject(BufferPool::GetInstance()->m_hSemaphoreBufferEmpty, INFINITE);
    		WaitForSingleObject(BufferPool::GetInstance()->mutex,INFINITE);                //the mutex P operation
    		BufferPool::GetInstance()->Produce();
    		Sleep(1000);
    		ReleaseMutex(BufferPool::GetInstance()->mutex);                                //resource semaphore P operation
    		ReleaseSemaphore(BufferPool::GetInstance()->m_hSemaphoreBufferFull,1,NULL);            //the mutex P operation
    	}
    	return 0;
    }

    运行效果


    展开全文
  • 【JAVA多线程】如何解决一个生产者与消费者问题

    万次阅读 多人点赞 2018-11-01 15:28:19
    如何解决一个生产者与消费者问题 生产者与消费者问题是多线程同步的一个经典问题生产者消费者同时使用一块缓冲区,生产者生产商品放入缓冲区,消费者从缓冲区中取出商品。我们需要保证的是,当缓冲区满时,生产...

                                 如何解决一个生产者与消费者问题

    生产者与消费者问题是多线程同步的一个经典问题。生产者和消费者同时使用一块缓冲区,生产者生产商品放入缓冲区,消费者从缓冲区中取出商品。我们需要保证的是,当缓冲区满时,生产者不可生产商品;当缓冲区为空时,消费者不可取出商品。

    下面介绍java中几种解决同步问题的方式

    (1)wait()与notify()方法

    (2)Lock与Condition机制

    (3)BlockingQueue阻塞队列

     

    【1】wait()与notify()方法

    这两个方法是object类中的方法

    wait()用在以下场合:

    (1)当缓冲区满时,缓冲区调用wait()方法,使得生产者释放锁,当前线程阻塞,其他线程可以获得锁。

    (2)当缓冲区空时,缓冲区调用wait()方法,使得消费者释放锁,当前线程阻塞,其他线程可以获得锁。

    notify()用在以下场合:

    (1)当缓冲区未满时,生产者生产商品放入缓冲区,然后缓冲区调用notify()方法,通知上一个因wait()方法释放锁的线程现在可以去获得锁了,同步块代码执行完成后,释放对象锁,此处的对象锁,锁住的是缓冲区。

    (2)当缓冲区不为空时,消费者从缓冲区中取出商品,然后缓冲区调用notify()方法,通知上一个因wait()方法释放锁的线程现在可以去获得锁了,同步块代码执行完成后,释放对象锁。

    代码演示:

    package day1101;
    
    import java.util.LinkedList;
    
    /**
     * 生产者消费者问题
     */
    public class ProAndCon {
        //最大容量
        public static final int MAX_SIZE = 2;
        //存储媒介
        public static LinkedList<Integer> list = new LinkedList<>();
    
        class Producer implements Runnable {
            @Override
            public void run() {
                synchronized (list) {
                    //仓库容量已经达到最大值
                    while (list.size() == MAX_SIZE) {
                        System.out.println("仓库已满,生产者" + Thread.currentThread().getName() + "不可生产.");
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    list.add(1);
                    System.out.println("生产者" + Thread.currentThread().getName() + "生产, 仓库容量为" + list.size());
                    list.notify();
                }
            }
        }
    
        class Consumer implements Runnable {
    
            @Override
            public void run() {
                synchronized (list) {
                    while (list.size() == 0) {
                        System.out.println("仓库为空,消费者" + Thread.currentThread().getName() + "不可消费.");
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    list.removeFirst();
                    System.out.println("消费者" + Thread.currentThread().getName() + "消费,仓库容量为" + list.size());
                    list.notify();
                }
            }
        }
    
    
        public static void main(String[] args) {
            ProAndCon proAndCon = new ProAndCon();
            Producer producer = proAndCon.new Producer();
            Consumer consumer = proAndCon.new Consumer();
    
            for (int i = 0; i < 10; i++) {
                Thread pro = new Thread(producer);
                pro.start();
                Thread con = new Thread(consumer);
                con.start();
            }
        }
    
    }
    

    运行结果:


    【2】Lock与Condition机制

    在JDK5.0之后,Java提供了Lock与Condition机制。Condition接口的await()和signal()是用来做同步的两种方法,它们的功能基本上和Object的wait()、nofity()相同,或者说可以取代它们,但是它们和Lock机制是直接挂钩的。通过在Lock对象上调用newCondition()方法,将条件变量和一个锁对象进行绑定,进而控制并发程序访问竞争资源的安全。

    代码演示:

    package day1101;
    
    import java.util.LinkedList;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ProAndCon2 {
        public static final int MAX_SIZE = 2;
        public static LinkedList<Integer> list = new LinkedList<>();
        public static Lock lock = new ReentrantLock();
        //仓库满的条件变量
        public static Condition full = lock.newCondition();
        //仓库空的条件变量
        public static Condition empty = lock.newCondition();
    
    
        class Producer implements Runnable {
    
            @Override
            public void run() {
                lock.lock();
                while (list.size() == MAX_SIZE) {
                    try {
                        System.out.println("仓库已满,生产者" + Thread.currentThread().getName() + "不可生产.");
                        full.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.add(1);
                System.out.println("生产者" + Thread.currentThread().getName() + "生产, 仓库容量为" + list.size());
                //唤醒其他生产者与消费者线程
                full.signal();
                empty.signal();
                lock.unlock();
            }
        }
    
        class Consumer implements Runnable {
    
            @Override
            public void run() {
                lock.lock();
                while (list.size() == 0) {
                    try {
                        System.out.println("仓库为空,消费者" + Thread.currentThread().getName() + "不可消费.");
                        empty.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.removeFirst();
                System.out.println("消费者" + Thread.currentThread().getName() + "消费,仓库容量为" + list.size());
                //唤醒其他生产者与消费者线程
                full.signal();
                empty.signal();
                lock.unlock();
            }
        }
    
    
        public static void main(String[] args) {
            ProAndCon2 proAndCon = new ProAndCon2();
            Producer producer = proAndCon.new Producer();
            Consumer consumer = proAndCon.new Consumer();
    
            for (int i = 0; i < 10; i++) {
                Thread pro = new Thread(producer);
                pro.start();
                Thread con = new Thread(consumer);
                con.start();
            }
        }
    
    
    }
    

    运行结果:


    【3】使用BlockingQueue阻塞队列

    什么是阻塞队列?

    如果向一个已经满了的队列中添加元素或者从空队列中移除元素,都将会导致线程阻塞,线程一直等待到有旧元素被移除或新元素被添加的时候,才能继续执行。符合这种情况的队列,称为阻塞队列。

    JDK 1.5 以后新增BlockingQueue接口,我们采用它实现类的其中两个类,ArrayBlockingQueue或者是LinkedBlockingQueue。

    怎么使用LinkedBlockingQueue?

    这里我们用LinkedBlockingQueue来解决生产者与消费者问题,主要用到它的两个方法,即put()与take()

    put():向阻塞队列中添加一个元素,队列满时,自动阻塞。

    take():从阻塞队列中取出一个元素,队列空时,自动阻塞。

    其实LinkedBlockingQueue底层使用的仍然是Lock与Condition机制,我们从源码就可以看出来

    //..............用到了Lock与Condition机制
    
    /** Lock held by take, poll, etc */
        private final ReentrantLock takeLock = new ReentrantLock();
    
        /** Wait queue for waiting takes */
        private final Condition notEmpty = takeLock.newCondition();
    
        /** Lock held by put, offer, etc */
        private final ReentrantLock putLock = new ReentrantLock();
    
        /** Wait queue for waiting puts */
        private final Condition notFull = putLock.newCondition();
    
    
    
    
    //...........put方法
    
    
    
    /**
         * Inserts the specified element at the tail of this queue, waiting if
         * necessary for space to become available.
         *
         * @throws InterruptedException {@inheritDoc}
         * @throws NullPointerException {@inheritDoc}
         */
        public void put(E e) throws InterruptedException {
            if (e == null) throw new NullPointerException();
            // Note: convention in all put/take/etc is to preset local var
            // holding count negative to indicate failure unless set.
            int c = -1;
            Node<E> node = new Node<E>(e);
            final ReentrantLock putLock = this.putLock;
            final AtomicInteger count = this.count;
            putLock.lockInterruptibly();
            try {
                /*
                 * Note that count is used in wait guard even though it is
                 * not protected by lock. This works because count can
                 * only decrease at this point (all other puts are shut
                 * out by lock), and we (or some other waiting put) are
                 * signalled if it ever changes from capacity. Similarly
                 * for all other uses of count in other wait guards.
                 */
                while (count.get() == capacity) {
                    notFull.await();
                }
                enqueue(node);
                c = count.getAndIncrement();
                if (c + 1 < capacity)
                    notFull.signal();
            } finally {
                putLock.unlock();
            }
            if (c == 0)
                signalNotEmpty();
        }
    
    
    
    
    //...........take方法
    
    
    
     public E take() throws InterruptedException {
            E x;
            int c = -1;
            final AtomicInteger count = this.count;
            final ReentrantLock takeLock = this.takeLock;
            takeLock.lockInterruptibly();
            try {
                while (count.get() == 0) {
                    notEmpty.await();
                }
                x = dequeue();
                c = count.getAndDecrement();
                if (c > 1)
                    notEmpty.signal();
            } finally {
                takeLock.unlock();
            }
            if (c == capacity)
                signalNotFull();
            return x;
        }

    看得出来,LinkedBlockingQueue底层已经解决好了同步问题,我们可以很方便的使用它。

    代码演示:

    package day1024;
    
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    /**
     * 解决生产者与消费者问题
     * 采用阻塞队列BlockingQueue
     */
    public class ProAndCon3 {
        public static final int MAX_SIZE = 2;
        public static BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(MAX_SIZE);
    
        class Producer implements Runnable {
            @Override
            public void run() {
                if (queue.size() == MAX_SIZE) {
                    System.out.println("仓库已满,生产者" + Thread.currentThread().getName() + "不可生产.");
                }
                try {
                    queue.put(1);
                    System.out.println("生产者" + Thread.currentThread().getName() + "生产, 仓库容量为" + queue.size());
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        class Consumer implements Runnable {
            @Override
            public void run() {
                if (queue.size() == 0) {
                    System.out.println("仓库为空,消费者" + Thread.currentThread().getName() + "不可消费.");
                }
                try {
                    queue.take();
                    System.out.println("消费者" + Thread.currentThread().getName() + "消费,仓库容量为" + queue.size());
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        public static void main(String[] args) {
            ProAndCon3 proAndCon = new ProAndCon3();
            Producer producer = proAndCon.new Producer();
            Consumer consumer = proAndCon.new Consumer();
    
            for (int i = 0; i < 10; i++) {
                Thread pro = new Thread(producer);
                pro.start();
                Thread con = new Thread(consumer);
                con.start();
            }
            
        }
    }
    

    运行结果就不贴了。

    展开全文
  • Java线程——生产者与消费者问题

    千次阅读 2021-01-17 23:11:14
    生产者与消费者问题 等待唤醒机制其实就是经典的“生产者与消费者”的问题。 该模式在现实生活中很常见,在项目开发中也广泛应用,它是线程间通信的经典应用。 生产者是一堆线程,消费者是另一堆线程,内存缓冲区...
  • 生产者与消费者问题是多线程中非常经典的线程同步问题,这些线程必须按照一定的生产率和消费率来访问共享缓冲区。实现方法是:设置两个信号量full和empty,其中full表示消费缓冲区的个数,empty表示生产缓冲区的个数...
  • 利用Windows提供的API函数,编写程序,解决生产者与消费者问题,实现进程的互斥与同步。 实验步骤与内容 进程的互斥与同步。编写一段程序,模拟生产者消费者线程,实现进程的互斥与同步。 利用VC++6.0实现上述...
  • 操作系统生产者与消费者问题代码实现

    万次阅读 多人点赞 2019-05-14 02:23:41
    问题分析: ①假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就...在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。他们之间也存在互斥,即生产者...
  • 生产者与消费者问题------legend050709

    千次阅读 2014-09-03 19:44:53
    (1.0)生产者消费者的背景 1》为了平衡生产者和消费者的处理能力,起到一个数据缓存的作用,同时也达到了一个解耦的作用 在多线程开发中,如果生产者生产数据的速度很快,而消费者消费数据的速度很慢,那么生产者就...
  • 互斥:保证一个资源只能被一个进程使用。 首先,解释“321”: 1、一个交易场所(缓冲区,类似于超市) ... 消费者与消费者互斥 生产者与消费者同步与互斥 在未做任何处理之前让生产者生产数据,消费者消费数
  • 多线程解决生产者与消费者问题

    千次阅读 2016-09-03 23:07:06
    生产者消费者问题是一个很有名的线程同步问题,以前学操作系统时,没怎么搞懂,直到现在学java学到多线程这一块才搞懂。该问题描述的是两个共享固定大小的缓冲区的线程问题。生产者的主要作用是生成一定量的数据放到...
  • 关于生产者与消费者的问题,百度百科上的定义是这样的:生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在...
  • [进程同步]—生产者与消费者问题

    千次阅读 多人点赞 2018-11-03 15:41:29
    生产者与消费者问题 PV操作是用来操作信号量的。 P:等待——wait——减法作用——阻塞作用 V:释放——signal——加法作用——唤醒作用 S.value &gt; 0 :有空闲CPU; S.value = 0...
  • 多线程之生产者与消费者问题

    千次阅读 2015-03-20 11:51:31
    生产者消费者问题(Producer-consumer problem):生产者不断地生产产品,消费者取走生产者生产的产品。生产者生产出产品后将其放到一个区域之中,消费者从这个地方去除数据。 涉及的问题:要保证生产者不会在缓冲...
  • 操作系统:使用临界区和互斥量两种方法实现简单生产者与消费者问题
  • 生产者与消费者问题是并发编程里面的经典问题,下面用wait()和notify()来实现消费者线程和生产者线程的并发执行。  说之前先讲几个概念:  wait()与sleep()的区别:  1.首先sleep()是Thread()类的方法,而...
  • 实验四 用信号量解决进程互斥与同步问题生产者与消费者问题模拟姓名 黄淋生 专业 网络工程 学号 201306114112 ...二、实验内容分析进程的同步与互斥现象,编程实现经典的进程同步问题——生产者消费者问题...
  • 操作系统:生产者与消费者问题

    千次阅读 2019-01-21 17:47:49
    使用信号量实现生产者-消费者问题  问题描述:使用一个缓冲区来保存物品,只有缓冲区没有满,生产者才可以放入物品;只有缓冲区不为空,消费者才可以拿走物品。 因为缓冲区属于临界资源,因此需要使用一个互斥量 ...
  • java多线程同步:生产者与消费者问题

    千次阅读 多人点赞 2013-10-24 16:54:18
    消费者与生产者问题是线程同步里边一个很经典的问题。 用通俗的语言来描述:一群生产者不断的生产产品,并将产品放到一个容器里边;同时一群消费者不断从容器里边消费产品。 容器的容量是有限的。如果容器满了,生产...
  • 各位看官们,大家好,上一回中咱们说的是进程知识体系图的例子,并且画了一张知识体系图。这一回咱们说的例子是:生产者与消费者问题。闲话休提,言归正转。让我们一起talk C栗子吧!
  • 生产者与消费者问题是指创建一组“生产者”线程和一组“消费者”线程,让他们进行同步互斥的运行,生产者生产一个产品,消费者就消费掉一个产品,下面我就用java的多线程来实现这个课题。
  • 生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将...
  • Windows线程(生产者与消费者问题

    千次阅读 2008-10-10 11:19:00
    Windows线程(生产者与消费者问题) 转载 佟强 2008.10.10 生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者...
  • 1.实验目标和要求进程的同步是操作系统处理机管理的重要内容,本实验要求学生理解生产者与消费者问题模型,掌握解决该问题的算法思想,学会使用同步机制。2.实验内容一组生产者向一组消费者提供消息,它们共享一个有...
  • 1. 问题描述有界缓冲区的生产者-消费者问题描述: 有一个或多个生产者线程生产某种类型的数据,并放置在缓冲区中;有一个或多个消费者线程从缓冲区中取数据并进行处理,每次取一项;在任何时候只能有一个生产者或...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 308,022
精华内容 123,208
关键字:

生产者与消费者问题