JUC:4_2并发协作模型:生产者消费者问题:if虚假唤醒,防止虚假唤醒

JUC:4_2并发协作模型:生产者消费者问题:if虚假唤醒,防止虚假唤醒

  • 线程之间的通信,如何交替执行?
  • 一个++一个--来操作
  • 两个++和两个--线程同时操作number
  • 问题怎么出现的:if和while
    • object的wait()为什么要用while来判断?

线程之间的通信,如何交替执行?

线程A、B操作同一个变量numbe=0


/**
 * 线程之间的通信,如何交替执行 ?
 * 线程A、B操作同一个变量numbe=0
 * A++
 * B--
 * 

* 问题: * 1.在只有两个线程存在的情况是安全的,再多一个++的和一个--的 */ public class TestCondition { public static void main(String[] args) { ServiceImpl service = new ServiceImpl(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { service.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { service.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { service.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { service.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "D").start(); } } class ServiceImpl { private int number = 0; //++ public synchronized void increment() throws InterruptedException { // if (number != 0) { while (number != 0) { //等待 this.wait(); } number++; System.out.println(Thread.currentThread().getName() + "===>" + number); //通知其他线程++完毕 this.notifyAll(); } //-- public synchronized void decrement() throws InterruptedException { // if (number == 0) { while (number == 0) { //等待 this.wait(); } number--; System.out.println(Thread.currentThread().getName() + "===>" + number); //通知其他线程--完毕 this.notifyAll(); } }

一个++一个–来操作

在只有两个线程++、–去操作,在只有两个线程存在的情况是安全的

A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0

两个++和两个–线程同时操作number

两个++和两个–线程同时操作number,都出现了负数

A===>1
B===>0
C===>1
A===>2
C===>3
B===>2
B===>1
B===>0
C===>1
A===>2
C===>3
B===>2
B===>1
B===>0
C===>1
D===>0
A===>1
D===>0
C===>1
B===>0
C===>1
D===>0
A===>1
D===>0
C===>1
B===>0
C===>1
D===>0
A===>1
D===>0
C===>1
B===>0
D===>-1
D===>-2
D===>-3
D===>-4
A===>-3

问题怎么出现的:if和while

怎么出现这种负数:
出现>1,消费者notiyall时,是另外一个正在wait的生产者抢到了锁,执行了++
出现<0,消费者notiyall时,是另外一个正在wait的消费者抢到了锁,执行了–

两个原因

  1. object的wait()方法会释放锁,与sleep抱着锁睡觉不同,释放锁之后,第二个线程就可以获取锁
  2. if只会判断一次,if判断,在if方法体没有执行完的情况下进入锁等待,等再次被唤醒重新时获取锁,不会再去做一次if判断,而是继续执行if里面的内容

if判断为空时,线程被阻塞,这时if判断就已经完成了,线程被唤醒会执行剩余操作

while判断为空时,线程被阻塞,这时while循环没有完成,线程被唤醒后会重新进行while判断

不用while自旋的话,如果多个消费者或者生产者会互相竞争共享资源

object的wait()为什么要用while来判断?

public final void wait() throws InterruptedException

导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。 换句话说,这个方法的行为就好像简单地执行呼叫wait(0) 。
当前的线程必须拥有该对象的显示器。 该线程释放此监视器的所有权,并等待另一个线程通知等待该对象监视器的线程通过调用notify方法或notifyAll方法notifyAll 。 然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。

像在一个参数版本中,中断和虚假唤醒是可能的,并且该方法应该始终在循环中使用:

  synchronized (obj) {
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action appropriate to condition
     } 

你可能感兴趣的:(并发编程,java,后端,经验分享,多线程,面试)