【JUC编程进阶】消费者生产者问题 防止虚假唤醒

synchronized版

package day3;

/**
 * @author jitwxs
 * @date 2021年05月11日 20:31
 */
/*
 * 线程之间通信问题:生产者消费者问题   等待唤醒,通知唤醒
 * 线程交替执行 A B 操作同一个变量 num = 0
 * A num+1
 * B num-1
 */
public class A {
        public static void main(String[] args) {
                Data data = new Data();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.increment();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"A").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.decrement();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"B").start();
        }
}

//判断等待,业务,通知
class Data{
        private  int num = 0;

        //+1
        public synchronized  void increment() throws Exception{
               if(num!=0){
                       //等待
                       this.wait();
               }
               num++;
                System.out.println(Thread.currentThread().getName()+"==>"+num);
               this.notifyAll();
        }
        //-1
        public synchronized void decrement() throws Exception{
                if(num==0){
                        //等待
                        this.wait();
                }
                num--;
                System.out.println(Thread.currentThread().getName()+"==>"+num);
                this.notifyAll();
        }
}

问题存在:如果存在A,B,C,D四个线程!虚假唤醒


`改成while可以解决`:
package day3;

/**
 * @author jitwxs
 * @date 2021年05月11日 20:31
 */
/*
 * 线程之间通信问题:生产者消费者问题   等待唤醒,通知唤醒
 * 线程交替执行 A B 操作同一个变量 num = 0
 * A num+1
 * B num-1
 */
public class A {
        public static void main(String[] args) {
                Data data = new Data();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.increment();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"A").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.decrement();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"B").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.increment();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"C").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.decrement();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"D").start();

        }
}

//判断等待,业务,通知
class Data{
        private  int num = 0;

        //+1
        public synchronized  void increment() throws Exception{
               while(num!=0){
                       //等待
                       this.wait();
               }
               num++;
                System.out.println(Thread.currentThread().getName()+"==>"+num);
               this.notifyAll();
        }
        //-1
        public synchronized void decrement() throws Exception{
                while(num==0){
                        //等待
                        this.wait();
                }
                num--;
                System.out.println(Thread.currentThread().getName()+"==>"+num);
                this.notifyAll();
        }
}

JUC版

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();

condition.await(); 等待
condition.signalAll(); 唤醒

package day3;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author jitwxs
 * @date 2021年05月11日 20:31
 */
/*
 * 线程之间通信问题:生产者消费者问题   等待唤醒,通知唤醒
 * 线程交替执行 A B 操作同一个变量 num = 0
 * A num+1
 * B num-1
 */
public class B {
        public static void main(String[] args) {
                Data2 data = new Data2();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.increment();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"A").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.decrement();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"B").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.increment();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"C").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                try {
                                        data.decrement();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                },"D").start();


        }
}

//判断等待,业务,通知
class Data2{
        private  int num = 0;
       Lock lock = new ReentrantLock();
       Condition condition = lock.newCondition();
        //+1
        public   void increment() throws Exception{
               lock.lock();
                try {
                        while(num!=0){
                                //等待
                               condition.await();
                        }
                        num++;
                        System.out.println(Thread.currentThread().getName()+"==>"+num);
                        condition.signalAll();
                } catch (InterruptedException e) {
                        e.printStackTrace();
                } finally {
                        lock.unlock();
                }
        }
        //-1
        public  void decrement() throws Exception{
                lock.lock();
                try {
                        while(num==0){
                                //等待
                            condition.await();
                        }
                        num--;
                        System.out.println(Thread.currentThread().getName()+"==>"+num);
                        condition.signalAll();
                } catch (InterruptedException e) {
                        e.printStackTrace();
                } finally {
                       lock.unlock();
                }
        }
}

  • 精准唤醒
package day3;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author jitwxs
 * @date 2021年05月12日 19:44
 */
/*
 * A执行完调用B,B执行完调用C
 */
public class C {
        public static void main(String[] args) {

                Data3 data3 = new Data3();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                data3.printA();
                        }


                },"A").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                        data3.printB();
                }


                },"B").start();
                new Thread(()->{
                        for (int i = 0; i < 10; i++) {
                                data3.printC();
                        }


                },"C").start();
        }


}
class Data3{  //资源类

      private   Lock lock = new ReentrantLock();
      private Condition condition1 = lock.newCondition();
      private Condition condition2 = lock.newCondition();
      private Condition condition3 = lock.newCondition();
      private int num = 1;  //1A,2B,3C
      public void printA(){
              lock.lock();


              try {//业务,判断,执行,通知
                     while (num!=1){
                             //等待
                             condition1.await();
                     }
                      System.out.println(Thread.currentThread().getName()+"====>AAAAA");
                     //唤醒指定的人
                      num = 2;
                      condition2.signal();

              } catch (Exception e) {
                      e.printStackTrace();
              } finally {
                      lock.unlock();
              }
      }

      public void printB(){
              lock.lock();


              try {//业务,判断,执行,通知
                        while(num!=2){
                                condition2.await();
                        }
                      System.out.println(Thread.currentThread().getName()+"=====>BBBBB");
                        num = 3;
                        condition3.signal();

              } catch (Exception e) {
                      e.printStackTrace();
              } finally {
                      lock.unlock();
              }

      }
      public void printC(){
              lock.lock();


              try {//业务,判断,执行,通知
                      while (num!=3){
                              condition3.await();
                      }
                      System.out.println(Thread.currentThread().getName()+"=====>CCCCCC");
                      num = 1;
                      condition1.signal();


              } catch (Exception e) {
                      e.printStackTrace();
              } finally {
                      lock.unlock();
              }
      }

}

你可能感兴趣的:(JUC编程,多线程,并发编程)