volatile是什么?
并行与并发
1.并发是指多个线程访问同一个资源(例如秒杀) 2.并行同时做多个事情 --通俗解释,参考 https://www.jianshu.com/p/cbf9588b2afb复制代码
volatile是什么
volatile是由JVM提供的轻量级的同步机制 volatile保证可见性和有序性(禁止指令重排序),但不保证原子性复制代码
JMM
(Java内存模型,Java Memory Model,简称JMM)
1.JMM本事是抽象的概念,并不真实存在,它描述的是一组规则或规范, 它定义了程序中的各个变量(实例变量、类变量和数组中的元素)的访问方式 2.JMM关于同步的规定: > 线程加锁前,必须读取主内存的最新值到自己的工作内存 > 线程解锁前,必须把共享变量的值刷新回主内存 > 加锁、解锁必须是同一把锁复制代码
JMM可见性
由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(也称栈空间),工作内存是每个线程私有的内存区域。
JMM规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问。
但线程对变量的读写必须在工作内存中进行。首先将变量从主内存拷贝到自己的工作内存中,然后对变量进行操作,操作完成后再蒋变量写回主内存,不能直接操作主内存中的变量。各个线程中的工作内存存储着主内存中的变量副本,某个线程对自己的变量副本的操作 其他线程默认是不会知道的,这就是内存可见性。JMM下共享变量的访问过程如下图:
volatile保证可见性验证
/** * <h1>验证volatile可见性</h1> * 共享变量 num 不使用volatile修饰 没有可见性 * ------------------------------------ * 共享变量 num 使用volatile修饰 保证可见性 * num被修改后会马上刷新主内存并通知其他线程重新读取 */ public class VolatileVisibilityDemo { public static void main(String[] args) { MyData myData = new MyData(); // 第一个线程 更新num = 60 new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t come in"); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } myData.addTo60(); System.out.println(Thread.currentThread().getName() + "\t update num: " + myData.num); }, "AAA").start(); // 第二个线程就是main线程 while (myData.num == 0) { // main线程一直等待循环 直到num值不等于0 System.out.println(Thread.currentThread().getName() + "\t 不知道有没有其他线程对num的修改,一直空转"); } System.out.println(Thread.currentThread().getName() + "\t 有其他线程对num的修改,退出空转," + "结束 num = " + myData.num); } } class MyData { volatile int num = 0; void addTo60() { num = 60; } }复制代码
根据JMM的规范,各个线程对于主内存中共享变量都是要先拷贝到自己的工作内存,然后对拷贝的副本进行读写然后再写回到主内存。
假如有一个线程A修改了共享变量X的值,但是还没有写回主内存。此时另外一个线程B对主内存中的共享变量X进行了回写,B线程的回写操作对于线程A来说并不可见,这种工作内存与主内存同步延迟现象就造成了可见性问题。
JMM原子性
volatile不保证原子性验证
作者:憋回去啊_再嚎踢死你
链接:https://juejin.cn/post/7021025381503205406