进程同步-生产者消费者问题

/**
 * Created by Leon on 2017/5/23.
 * 生产者消费者问题
 */
public class ProducerConsumer
{
    public static void main(String[] args)
    {
        syncstack ss=new syncstack();
        Producer p=new Producer(ss);
        Consumer c=new Consumer(ss);

        new Thread(p).start();//一个生产者
        new Thread(p).start();//一个生产者
        new Thread(p).start();//一个生产者
        new Thread(c).start();//一个消费者
    }
}

class wotou
{
    int id;
    wotou(int id)
    {
        this.id=id;
    }

    @Override
    public String toString()
    {
        return "wotou:"+id;
    }
}

class syncstack
{
    int index=0;//当前装到第几个wotou了
    wotou[] arrWT=new wotou[6];

    public synchronized void push(wotou wt)
    {
        while(index==arrWT.length)//用if比较危险,如果出现InterruptedException会跳出if语句出现错误
        {
            try
            {
                this.wait();//Object中的wait方法:当前的正在访问这个对象的线程wait;
                // 只能在synchronized的方法中用;wait后放弃对于锁的所有权
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
       //this.notify();//叫醒正在wait的线程;与wait方法成对出现
        this.notifyAll();//叫醒其他多个线程,不能叫醒自己;多个生产者消费者的时候使用
        arrWT[index]=wt;
        index++;
    }
    public synchronized wotou pop()
    {
        while(index==0)
        {
            try
            {
                this.wait();
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        //this.notify();
        this.notifyAll();
        index--;
        return arrWT[index];
    }
}

class Producer implements Runnable
{
    syncstack ss=null;
    Producer(syncstack ss)
    {
        this.ss=ss;
    }

    @Override
    public void run()
    {
        for (int i=0;i<20;i++)//每人生产20个wotou
        {
            wotou wt=new wotou(i);
            ss.push(wt);
            System.out.println("生产了:"+wt);
            try
            {
                Thread.sleep((int)(Math.random()*2));//1000个毫秒以内随机睡眠,控制生产速度
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}
class Consumer implements Runnable
{
    syncstack ss=null;
    Consumer(syncstack ss)
    {
        this.ss=ss;
    }

    @Override
    public void run()
    {
        for (int i=0;i<60;i++)//共有三个生产者生成60个wotou
        {
            wotou wt=ss.pop();
            System.out.println("消费了:"+wt);
            try
            {
                Thread.sleep((int)(Math.random()*1000));
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}



总结:wait()和sleep()的区别

wait()是Objec的方法,放弃进程锁

sleep()是Thread的方法,不放弃进程锁

生产者消费者问题是关于多线程或多进程同步的经典问题之一,通常用于解释如何正确地使用同步原语来避免数据竞争和死锁。 在生产者消费者问题中,有两个实体:生产者消费者生产者的职责是生产产品并将其放入缓冲区,而消费者的职责是从缓冲区中取出产品并消费它。缓冲区是一个有限的容器,可以容纳一定数量的产品。如果缓冲区已满,则生产者必须等待,直到有空间可用。如果缓冲区为空,则消费者必须等待,直到有产品可用。 为了避免竞争和死锁,我们需要使用同步原语来协调生产者消费者的操作。其中一个常见的解决方案是使用信号量。我们可以使用两个信号量:一个表示缓冲区中可用的空间数量,另一个表示已经放置在缓冲区中的产品数量。当生产者放置一个产品时,它会递增第二个信号量,并递减第一个信号量。当消费者取出一个产品时,它会递减第二个信号量,并递增第一个信号量。如果缓冲区已满或已空,则相应的信号量将被阻塞,从而防止生产者消费者继续操作。 下面是一个使用信号量解决生产者消费者问题的示例代码: ``` #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int in = 0; int out = 0; sem_t empty; sem_t full; pthread_mutex_t mutex; void *producer(void *arg) { int item; while (1) { item = rand() % 100; sem_wait(&empty); pthread_mutex_lock(&mutex); buffer[in] = item; printf("Producer produced %d at index %d\n", item, in); in = (in + 1) % BUFFER_SIZE; pthread_mutex_unlock(&mutex); sem_post(&full); } pthread_exit(NULL); } void *consumer(void *arg) { int item; while (1) { sem_wait(&full); pthread_mutex_lock(&mutex); item = buffer[out]; printf("Consumer consumed %d from index %d\n", item, out); out = (out + 1) % BUFFER_SIZE; pthread_mutex_unlock(&mutex); sem_post(&empty); } pthread_exit(NULL); } int main() { pthread_t prod_tid; pthread_t cons_tid; sem_init(&empty, 0, BUFFER_SIZE); sem_init(&full, 0, 0); pthread_mutex_init(&mutex, NULL); pthread_create(&prod_tid, NULL, producer, NULL); pthread_create(&cons_tid, NULL, consumer, NULL); pthread_join(prod_tid, NULL); pthread_join(cons_tid, NULL); sem_destroy(&empty); sem_destroy(&full); pthread_mutex_destroy(&mutex); return 0; } ``` 在这个示例中,我们有一个长度为10的缓冲区。生产者消费者都是无限循环的线程函数。生产者随机生成一个整数,并将其放入缓冲区中。消费者从缓冲区中取出一个整数并将其打印到控制台中。注意到我们使用了两个信号量:empty和full,它们分别表示缓冲区中可用的空间数量和已经放置在缓冲区中的产品数量。我们还使用一个互斥锁来确保生产者消费者的操作不会交叉进行。 在主函数中,我们初始化信号量和互斥锁,并创建两个线程:一个生产者和一个消费者。我们使用pthread_join函数等待线程完成并清理所有使用的资源。 这里提供的是一个基本的生产者消费者问题解决方案,还有其他的解决方案,例如使用条件变量或管程等。不同的解决方案适用于不同的场景,需要根据具体情况进行选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值