Demo

多线程学习笔记3——多线程的互斥和同步

线程的互斥

Producer是生产者线程, Consumer是消费者线程,Buffer是生产者与消费者的共享缓冲区, 必须实现读,写的同步.ProducerConsumerProblem 是演示生0read类,在run()创建了方法中生产6产品放到Buffer中,消费者Consumer创建了2个线程分别消费3个物品.

  • Buffer类中利用available变量实现了生产者生成出物品时可以消费.
    消费方法get()当available为false时,调用方法wait()等待.当available为true时消费,然后后把available改为false并调用notifyAll()唤醒生产者线程.
    生产方法put(),当available为true也就是容器为空时,生产者才可以想buffer中放产品,如果不能放则等待,放好后吧available改为true说明容器中有产品,消费这可以消费了,接着调用notifyAll()唤醒等待的消费者线程.

其中synchronize同步关键字,当一个线程用这个方法操作的时候,不允许其他线程对这个方法进行操作,从而保持主方法中创建的2个消费者线程保持互斥.

//生产者线程
class Producer extends Thread{
    private Buffer buffer;
    private int number;
    public Producer(Buffer buffer, int number){
        this.buffer = buffer;
        this.number = number;
    }
    public void run(){
        for (int i = 0;i < 6;){
            buffer.put(i);
            System.out.println("生产者#"+number+"生产"+(i++));
            try {
                Thread.sleep((int)(Math.random()*2000));
            }catch (InterruptedException exc){}
        }
    }
}
//消费者线程
class Consumer extends Thread{
    private Buffer buffer;
    private int number;

    public Consumer (Buffer buffer, int number){
        this.buffer = buffer;
        this.number = number;
    }
    public void run(){
        for (int i=0;i<3;i++){
            int v = buffer.get();
            System.out.println("消费这#"+number+"消费"+v);
        }
    }
}
//生产者与消费者共享的缓冲区,必须实现读,写的同步
class Buffer {
    private int contents;
    private boolean available = false;

    public synchronized int get() {
        while (!available) {
            try {
                //wait()会让线程挂起,直到通知到它继续执行!挂起的线程会存放到等待队列中,按照wait的先后顺序存放。
                this.wait();
            } catch (InterruptedException exc) {
            }
        }
        int value = contents;
        //消费着取出内容,改变存取控制available
        available = false;
        System.out.println("取出" + contents);
        //notify()通知等待队列中的第一个线程,notifyAll()通知的是等待队列中的所有线程
        this.notify();
        return value;
    }

    public synchronized void put(int value) {
        while (available) {
            try {
                this.wait();
            } catch (InterruptedException exc) {
            }
        }
        contents = value;
        //生成这放入内容,改变存取控制
        available = true;
        System.out.println("放入" + contents);
        this.notifyAll();
    }
}
public class ProducerConsumerProblem {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        new Producer(buffer,101).start();
        new Consumer(buffer,200).start();
        new Consumer(buffer,201).start();
    }
}

所以访问共享资源的方法都必须是synchronize的,否则程序肯定会出错.

线程的同步

原文地址:https://www.cnblogs.com/kongw/p/13893396.html