zoukankan      html  css  js  c++  java
  • volatile 关键字

    1.引入volatile的作用

    先跑一下这个程序:

    RunThread.java:

    package com.examp.jasonpeng;
    
    public class RunThread extends Thread {
    //    volatile private boolean isRunning = true;
        private boolean isRunning = true;
        public boolean isRunning(){
            return isRunning;
        }
        public void setRunning(boolean isRunning){
            this.isRunning = isRunning;
        }
    
        @Override
        public void run() {
    //        super.run();
            System.out.println("进入run了");
            while(isRunning == true){
    
            }
            System.out.println("线程被停止了!");
        }
    
    }
    public class Practise {
    //    static  final MyThread t = new MyThread();
    //    static Thread t1 = null, t2 =null;
    
        public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InterruptedException {
            try{
                RunThread thread = new RunThread();
                thread.start();
                Thread.sleep(1000);
                thread.setRunning(false);
                System.out.println("已经赋值为false");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    }

     是什么原因出现了死循环呢?

    原因是在启动RunThread.java 线程时,变量private boolean isRunning = true;存在于公共堆栈及线程的私有堆中。

    线程一直在私有堆栈中取得isRunning的值是true。而代码thread.setRunning(false);虽然被执行,更新的却是公共堆栈中的isRunning 变量值false,所以一直就是死循环的状态.

    内存结构如图:

     这个问题其实就是私有堆栈中的值和公共堆栈中的值不同步造成的。解决这样的问题就要使用volatile关键字了,它的主要作用就是当线程访问isRunning这个变量时,强制性从公共堆栈中进行取值。

    现将RunThread.java代码更改如下:

    package com.examp.jasonpeng;
    
    public class RunThread extends Thread {
        volatile private boolean isRunning = true;
    //    private boolean isRunning = true;
        public boolean isRunning(){
            return isRunning;
        }
        public void setRunning(boolean isRunning){
            this.isRunning = isRunning;
        }
    
        @Override
        public void run() {
    //        super.run();
            System.out.println("进入run了");
            while(isRunning == true){
    
            }
            System.out.println("线程被停止了!");
        }
    
    }

    程序运行结果:

    通过使用volatile关键字,强制的从公共内存中读取变量的值。

    内存结构如图:

     

     

    关键字volatile虽然增加了实例变量在多个线程之间的可见性,但它却不具备同步性,那么也就不具备原子性。

    下面来进行测试:

    MyThread.java:

    public class MyThread extends Thread{
        volatile public static int count;
        private static void addCount(){
            for(int i = 0;i<100;++i){
                count++;
            }
            System.out.println("count=" + count);
        }
    
        @Override
        public void run() {
            addCount();
        }
    }
    public class Practise {
    //    static  final MyThread t = new MyThread();
    //    static Thread t1 = null, t2 =null;
    
        public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InterruptedException {
           MyThread[] mythreadArray = new MyThread[100];
           for(int i =0;i<100;++i){
               mythreadArray[i] = new MyThread();
           }
           for(int i = 0;i<100;++i){
               mythreadArray[i].start();
           }
        }
    }

    运行结果如下:

     修改后的代码:

    public class MyThread extends Thread{
        volatile public static int count;
       synchronized private static void addCount(){ // 修改
            for(int i = 0;i<100;++i){
                count++;
            }
            System.out.println("count=" + count);
        }
    
        @Override
        public void run() {
            addCount();
        }
    }

     

     

     

     

  • 相关阅读:
    LF will be replaced by CRLF in package.json.
    JS 防抖和节流
    webpack依赖分析|打包优化
    JavaScript 中精度问题以及解决方案
    mysql查询某些数据的最小值
    mongodb sort
    常用的快捷键(用到时再不断完善)
    一、negut增加Nancy,和Nancy.Hosting.Self,
    Linux系统(Centos)安装tomcat和部署Web项目
    CentOS 7系统安装jdk-8u161-linux-x64.tar.gz
  • 原文地址:https://www.cnblogs.com/JasonPeng1/p/14454642.html
Copyright © 2011-2022 走看看