zoukankan      html  css  js  c++  java
  • 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()+"	"+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()+"	"+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()+"	"+number);
            //3 通知
            this.notifyAll();
        }
        public synchronized void decrement()throws Exception
        {
            //1 判断
            while(number == 0)
            {
                this.wait();
            }
            //2 干活
            number--;
            System.out.println(Thread.currentThread().getName()+"	"+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。

  • 相关阅读:
    ubuntu配置服务器环境
    discuz安装与学习资料
    前端面试题总结(一)
    css公共样式,初始化
    js的解析--预处理(三)
    sass的安装与基础
    移动开发学习笔记(一) 移动开发的注意事项
    移动前端一些常用的框架
    JavaScript的构造器与对象(二)
    JavaScript 中的Object的使用详解笔记(一)
  • 原文地址:https://www.cnblogs.com/qfdy123/p/14320243.html
Copyright © 2011-2022 走看看