java生產者和消費者問題,和if問題

package com.qcby.lock;

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

/**
 * @author HuangHaiyang
 * @date 2020/07/02
 * @description: description
 * @version: 1.0.0
 */
public class JucTest {
    public static void main(String[] args) {
        Goods goods=new Goods();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"一號").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"二號").start();
    }

    static class Goods{
        private int number=0;

        private Lock lock=new ReentrantLock();

        public synchronized void increment() throws InterruptedException {
            if (number!=0){
                this.wait();
            }

            number++;
            System.out.println(Thread.currentThread().getName()+"=====>"+number);
            this.notifyAll();
        }
        public synchronized void decrement() throws InterruptedException {
            if(number==0){
                this.wait();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"=====>"+number);
            this.notifyAll();
        }
    }
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0

}


一號=====>1
二號=====>0
一號=====>1
四號=====>0
三號=====>1
一號=====>2
二號=====>1
二號=====>0
一號=====>1
三號=====>2
四號=====>1
四號=====>0
三號=====>1
一號=====>2
二號=====>1
二號=====>0
一號=====>1
三號=====>2
四號=====>1
四號=====>0
三號=====>1
一號=====>2
二號=====>1
二號=====>0
一號=====>1
三號=====>2
四號=====>1
四號=====>0
三號=====>1
一號=====>2
二號=====>1
二號=====>0
一號=====>1
三號=====>2
四號=====>1
四號=====>0
三號=====>1
二號=====>0
三號=====>1
四號=====>0

Process finished with exit code 0

上述代碼在只有兩個線程時沒有問題。
但多個線程會出錯。我試了一下,確實會出錯。但是我不能明白爲什麼就會出錯。
不是有synchronized關鍵字加鎖了嗎?其實用if判斷的話,喚醒後線程會從wait之後的代碼開始運行,但是不會重新判斷if條件,直接繼續運行if代碼塊之後的代碼,而如果使用while的話,也會從wait之後的代碼運行,但是喚醒後會重新判斷循環條件,如果不成立再執行while代碼塊之後的代碼塊,成立的話繼續wait。

package com.qcby.lock;

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

/**
 * @author HuangHaiyang
 * @date 2020/07/02
 * @description: description
 * @version: 1.0.0
 */
public class JucTest {
    public static void main(String[] args) {
        Goods goods=new Goods();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"一號").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"二號").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"三號").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"四號").start();
    }

    static class Goods{
        private int number=0;

        private Lock lock=new ReentrantLock();

        public synchronized void increment() throws InterruptedException {
            while (number!=0){
                this.wait();
            }

            number++;
            System.out.println(Thread.currentThread().getName()+"=====>"+number);
            this.notifyAll();
        }
        public synchronized void decrement() throws InterruptedException {
            while(number==0){
                this.wait();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"=====>"+number);
            this.notifyAll();
        }
    }
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //一號=====>1
    //二號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //三號=====>1
    //四號=====>0
    //
    //Process finished with exit code 0

}


lock鎖實現

package com.qcby.lock;

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

/**
 * @author HuangHaiyang
 * @date 2020/07/02
 * @description: description
 * @version: 1.0.0
 */
public class JucTest {
    public static void main(String[] args) {
        Goods goods=new Goods();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"一號").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"二號").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"三號").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                try {
                    goods.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } },"四號").start();
    }

    static class Goods{
        private int number=0;

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

        public  void increment() throws InterruptedException {
            lock.lock();
            try {
                while (number!=0){
                    condition.await();
                }

                number++;
                System.out.println(Thread.currentThread().getName()+"=====>"+number);
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }
        public  void decrement() throws InterruptedException {
            lock.lock();
            try {
                while(number==0){
                    condition.await();
                }
                number--;
                System.out.println(Thread.currentThread().getName()+"=====>"+number);
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }
    }

}


精確通知

package com.qcby.lock;

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

/**
 * @author HuangHaiyang
 * @date 2020/07/02
 * @description: description
 * @version: 1.0.0
 */
public class JucTest {

    public static void main(String[] args) {
        Data3 data = new Data3();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.printA();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.printB();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.printC();
            }
        }, "C").start();
    }
}

class Data3 { // 資源類 Lock
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    private int number = 1; // 1A 2B 3C

    public void printA() {
        lock.lock();
        try {
// 業務,判斷-> 執行-> 通知
            while (number != 1) {
// 等待
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>AAAAAAA");
// 喚醒,喚醒指定的人,B
            number = 2;
            condition2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB() {
        lock.lock();
        try {
// 業務,判斷-> 執行-> 通知
            while (number != 2) {
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>BBBBBBBBB");
// 喚醒,喚醒指定的人,c
            number = 3;
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC() {
        lock.lock();
        try {
// 業務,判斷-> 執行-> 通知
// 業務,判斷-> 執行-> 通知
            while (number != 3) {
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName() + "=>BBBBBBBBB");
// 喚醒,喚醒指定的人,c
            number = 1;
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章