【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();
              }
      }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_树先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值