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 不能保证变量的原子性.

  • 相关阅读:
    mysql数据库监控利器lepus天兔工具安装和部署
    通过zabbix自带api进行主机的批量添加操作
    svn服务器的搭建备份和还原和svnmanager的使用
    elasticsearch自动按天创建索引脚本
    nginx或者squid正向代理实现受限网站的访问
    mysql查询sending data占用大量时间的问题处理
    解决由腾讯qq浏览器引起win10系统桌面图标不停的闪烁问题
    缓存系列之四:redis持久化与redis主从复制
    缓存系列之三:redis安装及基本数据类型命令使用
    缓存系列之二:CDN与其他层面缓存
  • 原文地址:https://www.cnblogs.com/superxuezhazha/p/12461307.html
Copyright © 2011-2022 走看看