生产者-消费者问题

生产者-消费者问题也称为有界缓冲区问题。

存在于多进程或多线程下,多个进程或线程读取同一个公共固定大小缓冲区产生的竞争。

参考:生产者-消费者维基百科


一般实现:

存在竞争条件。

消费者读取计数器发现为零,准备sleep(),消费者此刻不是sleep()状态;

进程切换,生产者生产数据放入缓冲区,调用wakeup(),然而消费者此刻不是sleep()状态,信号丢失。

进程切换,消费者调用sleep(),进入睡眠。

生产者一直生产数据放入缓冲区,直到缓冲区满。而消费者一直处于sleep()状态。


信号量(semaphore):

三个信号量:

mutex:此信号量用于互斥,保证一个时刻只有一个进程读写缓冲区和相关变量。初始值为1。

full:表示槽位不为空;初始值为0。

empty:槽位为空;初始值是缓冲区大小。


对信号量的两种操作:down up 

注:down 和 up操作是系统调用,通过TSL或XCHG指令来确保同一时刻只有一个cpu对信号量进行操作,可实现原子操作。

对生产者而言:顺序调用down(&empty),up(&full)。即减少一个空槽位,增加一个有数据的槽位。当槽位等于缓冲区大小,睡眠。

对消费者而言:顺序调用down(&full) ,up(&empty) 。即减少一个有数据的槽位,增加一个空槽位。当槽位数为零,睡眠。

其中,读和写操作放在down(&mutex) up(&mutex)之间,这样就可以实现只有一个线程被执行。

down(&mutex)
	新数据放入缓冲区/从缓冲区取出数据
up(&mutex)


管程(monitor):

摘自操作系统:

管程是一个由过程,变量及数据结构等组合成的一个集合,它们组成一个特殊的模块或软件包。

管程有一个很重要的特性,即任一时刻管程中只能有一个活跃进程,这一特性使管程能有效地完成互斥。

管程中采用两个条件变量:wait 和signal 。

当管程发现某个线程无法继续运行(如:生产者发现缓冲区变量),它会在某个条件变量上执行wait操作。

通过signal唤醒正在睡眠的进程。

其中java实现使用的是wait和notifyAll。

对多线程理解的不到位,感觉还是不懂。

附练习的代码。



java实现:(模拟多个生产者和消费者不限制次数运行)

生产者:

/**
 * 生产者
 * Created by bigliang on 2016/10/6.
 */
public class Producer extends Thread {
    String name;
    int needNum;
    Monitor monitor ;

    public Producer(String name,  Monitor monitor) {
        this.name = name;
        this.monitor = monitor;
    }

    @Override
    public void run() {
        Random random = new Random(47);
        while(true){
            needNum = random.nextInt(50)+1;
            monitor.produce(name,needNum);}
    }
}



消费者:

/**
 * 消费者
 * Created by bigliang on 2016/10/6.
 */
public class Consumer extends  Thread {
    String name;
    int needNum;
    Monitor monitor;

    public Consumer(String name,  Monitor monitor) {
        this.name = name;
        this.monitor = monitor;
    }

    @Override
    public void run() {
        Random random = new Random(47);
        while(true){
            needNum = random.nextInt(50)+1;
            monitor.consume(name,needNum);}
    }
}



管程:

/**
 * 管程
 * Created by bigliang on 2016/10/6.
 */
public class Monitor {
    public static  final  int NUM= 100; //定义缓冲区大小的常量
    public  int count = 0 ; //计数器


    /**
     *
     * @param name 哪一个消费者
     * @param size 消费量
     */
    public synchronized void consume(String name,int size){
        while(size > count ){
            System.out.println(name+":消费数量"+size+",大于剩余库存"+count+",无法消费,将进入wait()状态");
            try {
                wait(); //不满足,等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count  = count - size;       //满足
        System.out.println(name + ":消费" + size + ",目前总量是:" + count);
        notifyAll();     //唤醒wait()的线程

    }

    /**
     *
     * @param name 哪一个生产者
     * @param size 生产量
     */
    public synchronized void produce(String name,int size){
        while (size + count >= NUM){        //判断是否可以生产
            System.out.println(name+":生产数量"+size+",大于可生产数量"+(NUM - count)+",无法生产,将进入wait()状态");
            try {
                wait();  //不满足条件
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count = count + size;       //满足
        System.out.println(name+":生产"+size+",目前总量是:"+count);
        notifyAll();        //唤醒wait()的线程
    }
}

main()函数:

public class Main {

    public static void main(String[] args) {
        Monitor monitor = new Monitor();
        Random random = new Random(47);

        Producer p1 = new Producer("生产者1",monitor);
        Producer p2 = new Producer("生产者2",monitor);
        Producer p3 = new Producer("生产者3",monitor);

        Consumer c1 = new Consumer("消费者1",monitor );
        Consumer c2 = new Consumer("消费者2",monitor );
        Consumer c3 = new Consumer("消费者3",monitor );
        Consumer c4 = new Consumer("消费者4",monitor );
        Consumer c5 = new Consumer("消费者5",monitor );
        Consumer c6 = new Consumer("消费者6",monitor );
        Consumer c7 = new Consumer("消费者7",monitor );
        Consumer c8 = new Consumer("消费者8",monitor );
        Consumer c9 = new Consumer("消费者9",monitor );

        p1.start();
        p2.start();
        p3.start();

        c1.start();
        c2.start();
        c3.start();
        c4.start();
        c5.start();
        c6.start();
        c7.start();
        c8.start();
        c9.start();
    }
}

运行结果如下:(截取部分)

生产者2:生产9,目前总量是:9
生产者2:生产6,目前总量是:15
生产者2:生产44,目前总量是:59
生产者2:生产12,目前总量是:71
生产者2:生产12,目前总量是:83
生产者2:生产数量30,大于可生产数量17,无法生产,将进入wait()状态
生产者3:生产9,目前总量是:92
生产者3:生产6,目前总量是:98
生产者3:生产数量44,大于可生产数量2,无法生产,将进入wait()状态
生产者2:生产数量30,大于可生产数量2,无法生产,将进入wait()状态
消费者3:消费9,目前总量是:89
消费者3:消费6,目前总量是:83
消费者3:消费44,目前总量是:39
消费者3:消费12,目前总量是:27
消费者3:消费12,目前总量是:15
消费者3:消费数量30,大于剩余库存15,无法消费,将进入wait()状态
生产者2:生产30,目前总量是:45
生产者2:生产19,目前总量是:64
生产者2:生产1,目前总量是:65
生产者2:生产23,目前总量是:88
生产者2:生产8,目前总量是:96
生产者2:生产数量39,大于可生产数量4,无法生产,将进入wait()状态
消费者7:消费9,目前总量是:87
消费者7:消费6,目前总量是:81
消费者7:消费44,目前总量是:37
消费者7:消费12,目前总量是:25
消费者7:消费12,目前总量是:13
消费者7:消费数量30,大于剩余库存13,无法消费,将进入wait()状态
生产者3:生产44,目前总量是:57
生产者3:生产12,目前总量是:69
生产者3:生产12,目前总量是:81
生产者3:生产数量30,大于可生产数量19,无法生产,将进入wait()状态
消费者7:消费30,目前总量是:51
消费者7:消费19,目前总量是:32
消费者7:消费1,目前总量是:31
消费者7:消费23,目前总量是:8
生产者2:生产39,目前总量是:47
生产者2:生产29,目前总量是:76
生产者2:生产2,目前总量是:78
生产者2:生产数量40,大于可生产数量22,无法生产,将进入wait()状态
消费者3:消费30,目前总量是:48
消费者3:消费19,目前总量是:29
消费者3:消费1,目前总量是:28
消费者3:消费23,目前总量是:5
消费者3:消费数量8,大于剩余库存5,无法消费,将进入wait()状态
生产者2:生产40,目前总量是:45
生产者2:生产10,目前总量是:55
生产者2:生产29,目前总量是:84
生产者2:生产数量49,大于可生产数量16,无法生产,将进入wait()状态
消费者7:消费8,目前总量是:76
消费者7:消费39,目前总量是:37
消费者7:消费29,目前总量是:8
消费者7:消费2,目前总量是:6
消费者7:消费数量40,大于剩余库存6,无法消费,将进入wait()状态
消费者2:消费数量9,大于剩余库存6,无法消费,将进入wait()状态
生产者1:生产9,目前总量是:15
生产者1:生产6,目前总量是:21
生产者1:生产44,目前总量是:65
生产者1:生产12,目前总量是:77
生产者1:生产12,目前总量是:89
生产者1:生产数量30,大于可生产数量11,无法生产,将进入wait()状态
生产者3:生产数量30,大于可生产数量11,无法生产,将进入wait()状态
消费者6:消费9,目前总量是:80
消费者6:消费6,目前总量是:74
消费者6:消费44,目前总量是:30
消费者6:消费12,目前总量是:18
消费者6:消费12,目前总量是:6
消费者6:消费数量30,大于剩余库存6,无法消费,将进入wait()状态
消费者2:消费数量9,大于剩余库存6,无法消费,将进入wait()状态
消费者7:消费数量40,大于剩余库存6,无法消费,将进入wait()状态
生产者2:生产49,目前总量是:55
生产者2:生产12,目前总量是:67
生产者2:生产21,目前总量是:88
生产者2:生产9,目前总量是:97
生产者2:生产数量17,大于可生产数量3,无法生产,将进入wait()状态
消费者3:消费8,目前总量是:89
消费者3:消费39,目前总量是:50
消费者3:消费29,目前总量是:21
消费者3:消费2,目前总量是:19
消费者3:消费数量40,大于剩余库存19,无法消费,将进入wait()状态
生产者2:生产17,目前总量是:36
生产者2:生产41,目前总量是:77
生产者2:生产12,目前总量是:89
生产者2:生产数量23,大于可生产数量11,无法生产,将进入wait()状态
消费者5:消费9,目前总量是:80
消费者5:消费6,目前总量是:74
消费者5:消费44,目前总量是:30
消费者5:消费12,目前总量是:18
消费者5:消费12,目前总量是:6
消费者5:消费数量30,大于剩余库存6,无法消费,将进入wait()状态
消费者1:消费数量9,大于剩余库存6,无法消费,将进入wait()状态
消费者7:消费数量40,大于剩余库存6,无法消费,将进入wait()状态
消费者9:消费数量9,大于剩余库存6,无法消费,将进入wait()状态
消费者2:消费数量9,大于剩余库存6,无法消费,将进入wait()状态
消费者6:消费数量30,大于剩余库存6,无法消费,将进入wait()状态
生产者3:生产30,目前总量是:36
生产者3:生产19,目前总量是:55
生产者3:生产1,目前总量是:56
生产者3:生产23,目前总量是:79
生产者3:生产8,目前总量是:87
生产者3:生产数量39,大于可生产数量13,无法生产,将进入wait()状态
生产者1:生产数量30,大于可生产数量13,无法生产,将进入wait()状态
消费者8:消费9,目前总量是:78
消费者8:消费6,目前总量是:72
消费者8:消费44,目前总量是:28
消费者8:消费12,目前总量是:16
消费者8:消费12,目前总量是:4
消费者8:消费数量30,大于剩余库存4,无法消费,将进入wait()状态
消费者4:消费数量9,大于剩余库存4,无法消费,将进入wait()状态
生产者1:生产30,目前总量是:34
生产者1:生产19,目前总量是:53
生产者1:生产1,目前总量是:54
生产者1:生产23,目前总量是:77
生产者1:生产8,目前总量是:85
生产者1:生产数量39,大于可生产数量15,无法生产,将进入wait()状态
生产者3:生产数量39,大于可生产数量15,无法生产,将进入wait()状态
消费者6:消费30,目前总量是:55
消费者6:消费19,目前总量是:36
消费者6:消费1,目前总量是:35
消费者6:消费23,目前总量是:12
消费者6:消费8,目前总量是:4
消费者6:消费数量39,大于剩余库存4,无法消费,将进入wait()状态
消费者2:消费数量9,大于剩余库存4,无法消费,将进入wait()状态
消费者9:消费数量9,大于剩余库存4,无法消费,将进入wait()状态
消费者7:消费数量40,大于剩余库存4,无法消费,将进入wait()状态
消费者1:消费数量9,大于剩余库存4,无法消费,将进入wait()状态
消费者5:消费数量30,大于剩余库存4,无法消费,将进入wait()状态
生产者2:生产23,目前总量是:27
生产者2:生产5,目前总量是:32
生产者2:生产34,目前总量是:66
生产者2:生产7,目前总量是:73
消费者3:消费40,目前总量是:33
生产者2:生产26,目前总量是:59
生产者2:生产11,目前总量是:70
生产者2:生产数量43,大于可生产数量30,无法生产,将进入wait()状态
消费者5:消费30,目前总量是:40
消费者1:消费9,目前总量是:31
消费者7:消费数量40,大于剩余库存31,无法消费,将进入wait()状态
消费者9:消费9,目前总量是:22
消费者9:消费6,目前总量是:16
消费者9:消费数量44,大于剩余库存16,无法消费,将进入wait()状态
消费者2:消费9,目前总量是:7
消费者2:消费6,目前总量是:1
消费者2:消费数量44,大于剩余库存1,无法消费,将进入wait()状态
消费者6:消费数量39,大于剩余库存1,无法消费,将进入wait()状态
生产者3:生产39,目前总量是:40
生产者3:生产29,目前总量是:69
生产者3:生产2,目前总量是:71
生产者3:生产数量40,大于可生产数量29,无法生产,将进入wait()状态
生产者1:生产数量39,大于可生产数量29,无法生产,将进入wait()状态
消费者4:消费9,目前总量是:62
消费者4:消费6,目前总量是:56
消费者4:消费44,目前总量是:12
消费者4:消费12,目前总量是:0
消费者4:消费数量12,大于剩余库存0,无法消费,将进入wait()状态
消费者8:消费数量30,大于剩余库存0,无法消费,将进入wait()状态
生产者1:生产39,目前总量是:39
生产者1:生产29,目前总量是:68
生产者1:生产2,目前总量是:70
生产者1:生产数量40,大于可生产数量30,无法生产,将进入wait()状态
生产者3:生产数量40,大于可生产数量30,无法生产,将进入wait()状态
消费者6:消费39,目前总量是:31
消费者6:消费29,目前总量是:2
消费者6:消费2,目前总量是:0
消费者6:消费数量40,大于剩余库存0,无法消费,将进入wait()状态
消费者2:消费数量44,大于剩余库存0,无法消费,将进入wait()状态
消费者9:消费数量44,大于剩余库存0,无法消费,将进入wait()状态
消费者7:消费数量40,大于剩余库存0,无法消费,将进入wait()状态
消费者1:消费数量6,大于剩余库存0,无法消费,将进入wait()状态
消费者5:消费数量19,大于剩余库存0,无法消费,将进入wait()状态
生产者2:生产43,目前总量是:43
生产者2:生产25,目前总量是:68
生产者2:生产5,目前总量是:73
生产者2:生产1,目前总量是:74
生产者2:生产数量27,大于可生产数量26,无法生产,将进入wait()状态
消费者3:消费10,目前总量是:64
消费者3:消费29,目前总量是:35
生产者2:生产27,目前总量是:62
生产者2:生产23,目前总量是:85
消费者5:消费19,目前总量是:66
消费者1:消费6,目前总量是:60
消费者7:消费40,目前总量是:20
消费者9:消费数量44,大于剩余库存20,无法消费,将进入wait()状态
消费者2:消费数量44,大于剩余库存20,无法消费,将进入wait()状态
消费者6:消费数量40,大于剩余库存20,无法消费,将进入wait()状态
生产者3:生产40,目前总量是:60
生产者3:生产10,目前总量是:70
生产者3:生产29,目前总量是:99
生产者3:生产数量49,大于可生产数量1,无法生产,将进入wait()状态
生产者1:生产数量40,大于可生产数量1,无法生产,将进入wait()状态
消费者8:消费30,目前总量是:69
消费者8:消费19,目前总量是:50
消费者8:消费1,目前总量是:49
消费者8:消费23,目前总量是:26
消费者8:消费8,目前总量是:18
消费者8:消费数量39,大于剩余库存18,无法消费,将进入wait()状态
消费者4:消费12,目前总量是:6
消费者4:消费数量30,大于剩余库存6,无法消费,将进入wait()状态
消费者8:消费数量39,大于剩余库存6,无法消费,将进入wait()状态
生产者1:生产40,目前总量是:46
生产者1:生产10,目前总量是:56
生产者1:生产29,目前总量是:85
生产者1:生产数量49,大于可生产数量15,无法生产,将进入wait()状态
生产者3:生产数量49,大于可生产数量15,无法生产,将进入wait()状态
消费者6:消费40,目前总量是:45
消费者6:消费10,目前总量是:35
消费者6:消费29,目前总量是:6
消费者6:消费数量49,大于剩余库存6,无法消费,将进入wait()状态
消费者2:消费数量44,大于剩余库存6,无法消费,将进入wait()状态
消费者9:消费数量44,大于剩余库存6,无法消费,将进入wait()状态
消费者7:消费数量10,大于剩余库存6,无法消费,将进入wait()状态
消费者1:消费数量44,大于剩余库存6,无法消费,将进入wait()状态
消费者5:消费1,目前总量是:5
消费者5:消费数量23,大于剩余库存5,无法消费,将进入wait()状态
生产者2:生产47,目前总量是:52
生产者2:生产34,目前总量是:86
生产者2:生产数量35,大于可生产数量14,无法生产,将进入wait()状态
消费者3:消费49,目前总量是:37
消费者3:消费12,目前总量是:25
消费者3:消费21,目前总量是:4
消费者3:消费数量9,大于剩余库存4,无法消费,将进入wait()状态
生产者2:生产35,目前总量是:39
生产者2:生产45,目前总量是:84
消费者5:消费23,目前总量是:61
消费者5:消费8,目前总量是:53
消费者5:消费39,目前总量是:14
消费者5:消费数量29,大于剩余库存14,无法消费,将进入wait()状态
消费者1:消费数量44,大于剩余库存14,无法消费,将进入wait()状态
消费者7:消费10,目前总量是:4
消费者9:消费数量44,大于剩余库存4,无法消费,将进入wait()状态
消费者2:消费数量44,大于剩余库存4,无法消费,将进入wait()状态
消费者6:消费数量49,大于剩余库存4,无法消费,将进入wait()状态
生产者3:生产49,目前总量是:53
生产者3:生产12,目前总量是:65
生产者3:生产21,目前总量是:86
生产者3:生产9,目前总量是:95
生产者3:生产数量17,大于可生产数量5,无法生产,将进入wait()状态
生产者1:生产数量49,大于可生产数量5,无法生产,将进入wait()状态
消费者8:消费39,目前总量是:56
消费者8:消费29,目前总量是:27
消费者8:消费2,目前总量是:25
消费者8:消费数量40,大于剩余库存25,无法消费,将进入wait()状态
消费者4:消费数量30,大于剩余库存25,无法消费,将进入wait()状态
生产者1:生产49,目前总量是:74
生产者3:生产17,目前总量是:91

这里实现是加synchronized关键字。这个就可以保证不会发生竞争混乱的问题。


参考1:http://www.jasongj.com/java/multi_thread/

参考2:http://blog.csdn.net/monkey_d_meng/article/details/6251879

参考3:生产者-消费者维基百科


你可能感兴趣的:(操作系统,java,linux)