(一) Volatile是什么
Volatile 是Java虚拟机提供的轻量级的同步机制
- 保证可见性
- 不保证原子性
- 禁止指令重排
(二) JMM (Java内存模型 Java Memory Model)
是一种抽象概念,并不保证可见性,原子性,有序性
JMM关于同步的规定
- 线程解锁前,必须把共享变量的值刷新回内存
- 线程加锁前,必须读取主内存的最新值到自己的工作内存(自己线程私有数据区域)
- 加锁解锁是同一把锁
Java 内存模型中规定所有的变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问
但是线程对变量的操作必须在工作内存中进行,首先要将变量从主内存拷贝到自己的工作内存空间
然后对变量进行操作,操作完成后再将变量写回主内存
(三) Volatile 保证可见性 代码示例
Volatile可见性:及时通知其他线程,主物理内存的值已经被改变
不加Volatile
1 package com.Interview.study.thread; 2 import java.util.concurrent.TimeUnit; 3 class MyData{ 4 int number = 0; 5 public void addT060(){ 6 this.number = 60; 7 } 8 } 9 10 public class VolatileDemo { 11 12 public static void main(String[] args) { 13 MyData myData = new MyData(); 14 new Thread(() -> { 15 System.out.println(Thread.currentThread().getName() + " come in "); 16 try { 17 TimeUnit.SECONDS.sleep(3); 18 }catch (InterruptedException e){ 19 e.printStackTrace(); 20 } 21 myData.addT060(); 22 System.out.println(Thread.currentThread().getName() + " updated number value:" + myData.number); 23 },"AAA").start(); 24 25 while (myData.number == 0){ 26 27 } 28 29 System.out.println(Thread.currentThread().getName() + " mission is over "); 30 } 31 }
运行结果
加Volatile
1 package com.Interview.study.thread; 2 import java.util.concurrent.TimeUnit; 3 class MyData{ 4 volatile int number = 0; 5 public void addT060(){ 6 this.number = 60; 7 } 8 } 9 10 public class VolatileDemo { 11 12 public static void main(String[] args) { 13 MyData myData = new MyData(); 14 new Thread(() -> { 15 System.out.println(Thread.currentThread().getName() + " come in "); 16 try { 17 TimeUnit.SECONDS.sleep(3); 18 }catch (InterruptedException e){ 19 e.printStackTrace(); 20 } 21 myData.addT060(); 22 System.out.println(Thread.currentThread().getName() + " updated number value:" + myData.number); 23 },"AAA").start(); 24 25 while (myData.number == 0){ 26 27 } 28 29 System.out.println(Thread.currentThread().getName() + " mission is over "); 30 } 31 }
运行结果
(四) Volatile 不保证原子性 代码示例
1 package com.Interview.study.thread; 2 import java.util.concurrent.TimeUnit; 3 class MyData{ 4 volatile int number = 0; 5 public void addT060(){ 6 this.number = 60; 7 } 8 9 public void addNumber(){ 10 number++; 11 } 12 } 13 14 public class VolatileDemo { 15 16 public static void main(String[] args) { 17 MyData myData = new MyData(); 18 19 for(int i = 0 ; i < 20 ; i++){ 20 new Thread(() -> { 21 for(int j = 0 ;j < 1000 ; j++){ 22 myData.addNumber(); 23 } 24 },String.valueOf(i)).start(); 25 } 26 27 while (Thread.activeCount() > 2){ 28 Thread.yield(); 29 } 30 System.out.println(Thread.currentThread().getName() + " finally number value " + myData.number); 31 } 32 }
代码起了20个线程对其进行++ 1000次
预期结果应该是20000 但是执行结果有丢失
不保证原子性
(五)指令重排
多线程环境中线程交替执行,由于编译器优化重排的存在
两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测
细雨