Java多線程操作同一份資源


現在兩個線程,可以操作初始值為零的一個變量,實現一個線程對該變量加1,一個線程對該變量減1,實現交替,來10輪,變量初始值為零。

package com.yangyuanyuan.juc1205;


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

class Aircondition
{
    private int number = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increment()throws Exception
    {
        lock.lock();
        try
        {
            //1 判斷
            while (number != 0)
            {
                condition.await();//this.wait();
            }
            //2 干活
            number++;
            System.out.println(Thread.currentThread().getName()+"\t"+number);
            //3 通知
            condition.signalAll();//this.notifyAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void decrement()throws Exception
    {
        lock.lock();
        try
        {
            //1 判斷
            while (number == 0)
            {
                condition.await();//this.wait();
            }
            //2 干活
            number--;
            System.out.println(Thread.currentThread().getName()+"\t"+number);
            //3 通知
            condition.signalAll();//this.notifyAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    /*public synchronized void increment()throws Exception
    {
        //1 判斷
        while (number != 0)
        {
            //AAA  CCC
            this.wait();
        }
        //2 干活
        number++;
        System.out.println(Thread.currentThread().getName()+"\t"+number);
        //3 通知
        this.notifyAll();
    }
    public synchronized void decrement()throws Exception
    {
        //1 判斷
        while(number == 0)
        {
            this.wait();
        }
        //2 干活
        number--;
        System.out.println(Thread.currentThread().getName()+"\t"+number);
        //3 通知
        this.notifyAll();
    }*/

}

/**
    1    高聚低合前提下,線程操作資源類
    2   判斷/干活/通知
    3   防止虛假喚醒 不能使用if判斷,會出現2

   知識小總結 = 多線程編程套路+while判斷+新版寫法
 */
public class ProdConsumerDemo04
{
    public static void main(String[] args)throws  Exception
    {
        Aircondition aircondition = new Aircondition();

        new Thread(() -> {
            for (int i = 1; i <=10; i++)
            {
                try
                {
                    Thread.sleep(200);
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(() -> {
            for (int i = 1; i <=10; i++)
            {
                try
                {
                    Thread.sleep(300);
                    aircondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

        new Thread(() -> {
            for (int i = 1; i <=10; i++)
            {
                try
                {
                    Thread.sleep(400);
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"C").start();
        new Thread(() -> {
            for (int i = 1; i <=10; i++)
            {
                try
                {
                    Thread.sleep(500);
                    aircondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"D").start();

    }
}

使用if判斷存在虛假喚醒情況,變量可能會變成2

如圖所示,如果只有兩個線程,一個線程加,一個線程減,不會存在虛假喚醒情況(選無可選)。

當變成四個線程時,兩個線程加,兩個線程減,使用if就會存在虛假喚醒情況。如變量初始為0(0!=0為false),執行完+’變量變成1,此時+線程進來發現值為1等待(this.wait()處等待,未出if判斷),然后+‘線程又進來發現值為1它也等待(this.wait()處等待,未出if判斷),此時-線程進來(1==0為false)發現變量值為1將變量做減法變成0。由於此時+和+‘仍在等待,cpu為了降低消耗量和負擔,會先滿足等待時間長的線程(線程優先級會高)

由於使用的是if,不會再拉回來重新判斷一次(兩個線程this.wait()處等待),+和+’線程都會做加法,變量值就變成了2。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM