线程间通信机制--wait与notify的使用?为什么要放在synchronized代码块内?

关于wait和notify的使用,在此我们使用链表模拟队列Q,使用synchronized用于实现多线程的同步操作,在特定条件下释放线程持有的锁,然后挂起,等待条件满足进行资源竞争.


import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: jaden
 * @Date: 2019/5/20 16:44
 * @Version 1.0
 */
public class MyQueue {

    // 使用链表模拟队列
    private final LinkedList list = new LinkedList<>();
    // 计数器(原子操作)
    private AtomicInteger count = new AtomicInteger(0);
    // 下限初始化为0
    private final int minSize = 0;
    // 上限初始化为5
    private final int maxSize = 5;

    private final Object lock = new Object();

    public void offer(Object obj) {
        synchronized (lock) {
            while (count.get() == this.maxSize) {
                try {
                    // 释放掉线程持有的锁并挂起线程
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 生产
            list.offer(obj);
            System.out.println("加入数据:" + obj);
            count.incrementAndGet();
            // 唤醒线程
            lock.notify();
        }
    }

    public Object consume() {
        Object ret = null;
        synchronized (lock){
            while (count.get() == this.minSize) {
                try {
                    // 释放掉线程持有的锁并挂起线程
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 消费
            ret = list.remove();
            count.decrementAndGet();
            // 唤醒线程
            lock.notify();
        }
        return ret;
    }

    public int getSize() {
        return this.list.size();
    }

    public static void main(String[] args) {
        MyQueue mq = new MyQueue();
        mq.offer("1");
        mq.offer("2");
        mq.offer("3");
        mq.offer("4");
        mq.offer("5");
        System.out.println("当前Q长度:" + mq.getSize());

        Thread t1 = new Thread(new Runnable(){
            @Override
            public void run() {
                mq.offer("6");
            }
        },"线程T1");
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                Object o1 = mq.consume();
                System.out.println("移除数据:" + o1);
            }
        },"线程T2");

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
} 
  

 

wait与notify为什么要放在synchronized代码块内?

下面我们看下wait()方法到底做了什么:

调用了wait()后, 当前线程会释放该对象持有的锁, 然后当前线程会被添加到该对象的等待队列上, 等待条件再次参与锁竞争。 因为wait()方法会强迫线程首先进行释放锁操作,所以wait()方法应该先获取锁,这就解答了wait为什么要放在synchronized代码块内。

notify()与wait()成对使用,当一个线程调用一个对象的notify()方法时,调度器会从等待队列中任意取出一个线程, 将其添加到入口队列中。入口队列中的多个线程就会竞争对象的锁, 得到锁的线程就可以继续执行, 如果等待队列中没有线程,notify()方法也不会抛出异常。

notifyAll()会将等待队列中所有的线程都唤醒,因此在实际中 notifyAll()比notify()更常用 。

你可能感兴趣的:(JAVA,多线程)