• volatile关键字小结


    Java 提供了一种稍弱的同步机制,即 volatile 变量,用来确保将变量的更新操作通知到其他线程。可以将 volatile 看做一个轻量级的锁,但是又与锁有些不同:
    1. 对于多线程,不是一种互斥关系
    2. 不能保证变量状态的“原子性操作”

    在没有用volatile关键字修饰的demo

    /**
     * Volatile 关键字:当多线程操作共享数据时,可以保证内存数据的可见性,
     * 相较于synchronized来说是一种比较轻量级的同步策略。
     * 注意:
     * 1. Volatile不能保证变量的原子性。
     * 2. 不具备互斥性
     * Created by 吴海飞 on 2017-1-23.
     */
    public class TestVolatile {
        public static void main(String[] args){
            volatileDemo volatileDemo = new volatileDemo();
            new Thread(volatileDemo).start();
    
            while (true){
                if(volatileDemo.isFlag()){
                    System.out.println("------------------");
                    break;
                }
            }
    
        }
    }
    
    class volatileDemo implements Runnable{
    
        private boolean flag = false;
    
        @Override
        public void run() {
    
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
            }
            flag = true;
            System.out.println("flag=" + isFlag());
        }
        public boolean isFlag() {
            return flag;
        }
    
        public void setFlag(boolean flag) {
            this.flag = flag;
        }
    
    }
    
    • 代码运行后会出现这种状况如下图所示:

    • 出现这种状况的原因是:
      主线程与子线程并发执行,在子线程拿到flag=false的同时,主线程也拿到了flag=false,之后子线程将flag变为true,并打印出flag,结束线程。主线程因为读取到的flag = false,所以一直处于死循环状态中无法结束线程任务。

    • 具体分析如下图所示:
      这里写图片描述

    • 将flag变量设置成 volatile的,这样问题就解决了。
      当子线程将flag关键字改变时,将flag从子线程的缓冲区写入到内存中,这样主线程读到的flag变成true了,所以问题就解决了。

  • 相关阅读:
    spring 事务
    Servlet详解之两个init方法的作用
    被request.getLocalAddr()苦闷了很久
    Java获取IP地址:request.getRemoteAddr()警惕
    MongoDB笔记
    hexo+github搭建博客
    Python处理Excel(使用openpyxl库)
    Wireshark使用学习
    查看开启操作系统端口
    记录Centos7服务器搭建过程
  • 原文地址:https://www.cnblogs.com/haifeiWu/p/9079586.html
Copyright © 2020-2023  润新知