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

    1 内存可见性问题

    class flagTest implements Runnable{
        private boolean flag = false;
    
        @Override
        public void run() {
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag=true;
            System.out.println("flag="+flag);
        }
        public boolean getFlag(){
            return flag;
        }
    }
    public class volatileTest {
        public static void main(String[] args) {
            flagTest ft = new flagTest();
            Thread thread = new Thread(ft);
            thread.start();
            while (true){
                if(ft.getFlag()) System.out.println("----------");
            }
    
        }
    View Code

    如上的程序,主线程会一直在while里面死循环. 这是因为,java程序在主内存里创建了一个flag=false.线程1和主线程读取flag的时候,分别复制了一份.当线程1对flag的值进行修改之后,由于主线程存在flag的副本,且while(true)效率极高,所以没有刷新flag的值,导致主线程陷入死循环.这就是共享变量的内存不可见问题.

    要解决这个问题,可以使用synchronized加锁,这样在访问共享变量的时候,就会刷新内存变量.但是弊端是,程序执行效率大幅度下降.

    public class volatileTest {
        public static void main(String[] args) {
            flagTest ft = new flagTest();
            Thread thread = new Thread(ft);
            thread.start();
            while (true){
                synchronized (ft){
                    if(ft.getFlag()) {
                        System.out.println("----------");
                        break;
                    }
    
                }
    
            }
    
        }
    main函数修改为这样

    使用volatile关键字,可是使得共享变量的内存可见性提高,可以理解为不同的线程直接在主内存里面访问共享变量.

    class flagTest implements Runnable{
        private volatile boolean flag = false;
    
        @Override
        public void run() {
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag=true;
            System.out.println("flag="+flag);
        }
        public boolean getFlag(){
            return flag;
        }
    }
    public class volatileTest {
        public static void main(String[] args) {
            flagTest ft = new flagTest();
            Thread thread = new Thread(ft);
            thread.start();
            while (true){
                    if(ft.getFlag()) {
                        System.out.println("----------");
                        break;
    
                }
    
            }
    
        }
    View Code
    private volatile boolean flag = false;

    volatile具有以下特点:

      当线程之间进行数据共享时,使用volatile关键字修饰,可以使得共享变量内存可见,相比与synchronized,它是一种轻量级的线程锁.

      1 不具有互斥性

      2 不能保证变量的原子性.

  • 相关阅读:
    基于OpenVINO的端到端DL网络-A Year in Computer Vision中关于图像增强系列部分
    基于OpenVINO的端到端DL网络-Tesseract5+VS2017+win10源码编译攻略
    基于OpenVINO的端到端DL网络-Intel AI DevCloud 的申请和登陆
    OpenCV和RTSP的综合研究
    基于OpenVINO的端到端DL网络-包含目录、库目录、附加包含目录、附加库目录、附加依赖项之详解【正确的目录添加方法】
    消除临时对象
    Redis数据导入工具优化过程总结
    清楚利弊,用好内联
    STL区间成员函数及区间算法总结
    高效的使用STL
  • 原文地址:https://www.cnblogs.com/superxuezhazha/p/12461307.html
Copyright © 2011-2022 走看看