多线程操作

题目:

* 题目:现在两个线程,可以操作初始值为零的一个变量,
* 实现一个线程对该变量加1,一个线程对该变量减1,
* 实现交替,来10轮,变量初始值为零。

 

看代码:

package com.cxy.juc;


class AirCondition{
    private int num = 0;
    public synchronized void increment() throws Exception{
        if(num !=0){
            this.wait();
        }
        num++;
        System.out.println(Thread.currentThread().getName()+"\t"+num);
        this.notifyAll();
    }
    public synchronized void decrement() throws Exception{
        if (num ==0){
            this.wait();
        }
        num--;
        System.out.println(Thread.currentThread().getName()+"\t"+num);
        this.notifyAll();
    }
}

/**
 * 多线程操作:  线程操作资源类,
 * 判断,干活,通知
 * 防止虚假唤醒
 */
public class ProdConsumerDemo {
    public static void main(String[] args) throws Exception{
        AirCondition airCondition =new AirCondition();

        new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"a").start();

        /*new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"c").start();*/
        new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"b").start();

       /* new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"d").start();*/
    }

}

执行结果是对的,

a    1
b    0
a    1
b    0
a    1
b    0
a    1
b    0
a    1
b    0
a    1

 

那么线程再增多呢,变成两个线程增加两个线程减少呢:

package com.cxy.juc;


class AirCondition{
    private int num = 0;
    public synchronized void increment() throws Exception{
        if(num !=0){
            this.wait();
        }
        num++;
        System.out.println(Thread.currentThread().getName()+"\t"+num);
        this.notifyAll();
    }
    public synchronized void decrement() throws Exception{
        if (num ==0){
            this.wait();
        }
        num--;
        System.out.println(Thread.currentThread().getName()+"\t"+num);
        this.notifyAll();
    }
}

/**
 * 多线程操作:  线程操作资源类,
 * 判断,干活,通知
 * 防止虚假唤醒
 */
public class ProdConsumerDemo {
    public static void main(String[] args) throws Exception{
        AirCondition airCondition =new AirCondition();

        new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"a").start();

        new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"c").start();
        new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"b").start();

        new Thread(() ->{
            for (int i = 0; i <10 ; i++) {
                try {
                    airCondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"d").start();
    }

}

看结果:

b    0
c    1
d    0
a    1
d    0
c    1
b    0
d    -1
d    -2
a    -1
b    -2
b    -3
a    -2

那么出现bug了,而且是api级别的bug,怎么办呢,

多线程操作:高内聚低耦合,线程操作资源类,判断,干活,通知,防止虚假唤醒

那么在那个里面就需要在判断的时候,虚假唤醒了;

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
     } 该方法只能由作为该对象的监视器的所有者的线程调用。 有关线程可以成为监视器所有者的方式的说明,请参阅notify方法。 
异常 
IllegalMonitorStateException - 如果当前线程不是对象监视器的所有者。 
InterruptedException - 如果任何线程在当前线程等待通知之前或当前线程中断当前线程。 当抛出此异常时,当前线程的中断状态将被清除。 
另请参见: 
notify() , notifyAll() 

所以需要将if判断变成while判断:

a    1
b    0
c    1
d    0
a    1
b    0
c    1
d    0
a    1
b    0
c    1
d    0
a    1
d    0
c    1
d    0

 

结果就对了

 

上一篇:java锁与监视器概念 为什么wait、notify、notifyAll定义在Object中 多线程中篇(九)


下一篇:多线程等待和通知模式例子(wait()和notifyAll()应用)