生产者消费者问题、防止虚假唤醒

生产者消费者问题、防止虚假唤醒

传统synchronized

package JUC;
/**   
 * Copyright © 2021 eSunny Info. Tech Ltd. All rights reserved.
 * 
 * 功能描述:生产者
 * 操作同一个变量 通知等待唤醒
 * Provider num + 1
 * Consumer num - 1
 */
public class ProviderConsumer {
	
	public static void main(String[] args) {
		Data data = new Data();
		new Thread(()->{
			for (int i = 0; i < 10; i++) {
				try {
					data.increment();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"A") .start();
		
		new Thread(()->{
			for (int i = 0; i < 10; i++) {
				try {
					data.decrement();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"B") .start();
	}
}

class Data{//数字 资源类
	
	private int number = 0;
	
	// +1
	public synchronized void increment() throws InterruptedException {
		if (number!=0) {
			//等待减少
			this.wait();
		}
		number++;
		System.out.println(Thread.currentThread().getName() + "票数加 +"+ number);
		
		//通知
		this.notifyAll();
	}
	
	// -1
	public synchronized void decrement() throws InterruptedException {
		if (number==0) {
			//等待增加
			this.wait();
		}
		number--;
		System.out.println(Thread.currentThread().getName() + "票数减 -"+ number);
		
		//通知
		this.notifyAll();
	}
	
}

在这里插入图片描述
2个线程看起来没有问题,但是当打开4个线程呢?

防止虚假唤醒

线程也可以唤醒,而不会被通知,中断或超时,即所谓的虚假唤醒。虽然实践中很少发生,但应用程序必须通过测试应该使线程被唤醒的条件来防范,并且如果条件不满足则继续等待。换句话讲,等待应该总是出现在循环中:
将if 修改成while循环判断
在这里插入图片描述

lock锁 生产消费者

在这里插入图片描述

package JUC;

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

/**   
 * Copyright © 2021 eSunny Info. Tech Ltd. All rights reserved.
 * 
 * 功能描述:
 * @Package: JUC 
 * @author: 79283   
 * @date: 2021年1月20日 下午7:13:51 
 */
public class ProviderConsumerJUC {
	
	public static void main(String[] args) {
		DataJUC data = new DataJUC();
		new Thread(()->{
			for (int i = 0; i < 10; i++) {
				try {
					data.increment();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"A") .start();
		
		new Thread(()->{
			for (int i = 0; i < 10; i++) {
				try {
					data.decrement();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"B") .start();
		
		new Thread(()->{
			for (int i = 0; i < 10; i++) {
				try {
					data.increment();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"C") .start();
		
		new Thread(()->{
			for (int i = 0; i < 10; i++) {
				try {
					data.decrement();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"D") .start();
	}
}

class DataJUC{//数字 资源类
	
	private int number = 0;
	
	Lock lock = new ReentrantLock();
	//Condition 等待唤醒
	Condition newCondition = lock.newCondition();
	Condition newCondition2 = lock.newCondition();
	
	// +1
	public void increment() throws InterruptedException {
		lock.lock();
		try {
			while (number!=0) {
				//等待减少
				newCondition.await();
			}
			number++;
			System.out.println(Thread.currentThread().getName() + "票数加 +"+ number);
			
			//通知
			newCondition.signalAll();
		} catch (Exception e) {
			e.getStackTrace();
		} finally {
			lock.unlock();
		}
		
	}
	
	// -1
	public void decrement() throws InterruptedException {
		lock.lock();
		try {
			while (number==0) {
				//等待增加
				newCondition.await();
			}
			number--;
			System.out.println(Thread.currentThread().getName() + "票数减 -"+ number);
			
			//通知
			newCondition.signalAll();
		} catch (Exception e) {
			e.getStackTrace();
		} finally {
			lock.unlock();
		}
		
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一只小小狗

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

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

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

打赏作者

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

抵扣说明:

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

余额充值