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

    volatile作用

    volatile的作用是可以保持共享变量的可见性,即一个线程修改一个共享变量后,另一个线程能够读取到这个修改后的值。

    先来看一个问题:

    定义一个Task类

    package com.sutaoyu.volatlt;
    
    public class Task implements Runnable{
        private boolean flag = true;
        
        public boolean isFlag() {
            return flag;
        }
        
        public void setFlag(boolean flag) {
            this.flag = flag;
        }
        
        public void run() {
            while(flag) {
                System.out.println("while循环");
            }
            System.out.println("结束循环");
        }
    }

    使用多线程执行上面的类

    package com.sutaoyu.volatlt;
    
    public class VolatileTest01 {
        public static void main(String[] args) throws InterruptedException {
            Task task = new Task();
            
            Thread t1 = new Thread(task);
            t1.start();
            Thread.sleep(10);
            
            //在主线程中将task对象中的flag设置为false
            task.setFlag(false);
        }
    }

    上面程序中在64位的机器上以server模式运行时,有可能会出现死循环的现象。

    JVM的运行可以分为下面两种模式:

    • client:启动快,运行后性能不如server模式,一般运行时默认是client模式
    • server:启动慢,运行后性能比client模式好。

    在eclipse中可以通过配置来使用server模式,右键—>run as—>run configurations。在下图中红框的位置写上-server。然后点击run即可

    上面程序出现问题的原因这样的,虽然在主线程中将flag的设置为false,但是jvm为了提升效率,t1线程一直在私有内存中获取flag的值,而私有内存中的flag值并没有被改变,所以导致死循环的发生。

    volatile关键字

    使用volatile修饰flag解决上面问题:

    volatile private boolean flag = true;

    将flag声明为volatile后,t1线程会从公共的内存中访问flag的值,这样在主线程将flag设置为false后,t1线程中的循环就会结束了。

    注意:volatile只能修饰变量,不能修饰方法

    原子性和非原子性

    原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。

    非原子性:不符合原子性的就是非原子性

    请问下面语句中那个是原子性的操作

    int x = 1024; //语句1
    
    int y = x; //语句2
    
    x++; //语句3
    
    x = x + 1; //语句4

    语句1:是原子性的。
    语句2:cpu先去内存中读取x的值,读取后在为y进行赋值,在读取后给y赋值前的这段时间可能会切换到其他线程上面。
    语句3:包含了三个操作,先读取x的值,然后进行加1操作,最后写入新的值,在这三个操作的间隙可能会切换到其他线程上面。
    语句4:同上

    如果一段程序是具有原子性的,那么这段程序就不会出现线程安全问题。

  • 相关阅读:
    Android 杀掉当前程序的进程
    Android Studio 2.3更换默认的ConstraintLayout布局
    Android ConstraintLayout约束控件链接整理
    Java 实现字符串反转
    Android 网络技术HTTP
    数据库框架 Litepal
    Android FastJson解析
    Java类的初始化顺序
    Android 免费短信获取国家列表和国家代码
    【转】仿Android 联系人SideBar排序,根据拼音A-Z字母快速导航,以及输入搜索条件过滤,显示姓名的文字图片
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/10160941.html
Copyright © 2011-2022 走看看