Volatile的理解
Volatile是Java 虚拟机提供--轻量级的同步机制--
- 保证可见性
保持刷新主内存属性 - 不保证原子性
不可分割
线程A在执行任务的时候,不能被打扰的,也不能被分割。要么同时成功,要么同时失败。
可以用lock/synchronized解决
也可以用原子类AtomicInteger操作解决 - 禁止指令重排
什么是指令重排? 计算机并不是按照我们写的程序那样去执行
源代码---编译器重排---指令并行也可能会重排---内存系统也会重排----执行
处理器在执行指令重排的时候,考虑之间的依赖性!
由于内存屏障,可以保证避免指令重排的想象产生
int x=1; //1
int y=2; //2
x=x+5; //3
y=x*x; //4
我们期望1234,但执行可能1324,2134
但不会4123
什么是JMM
JMM : Java内存模型,不存在的东西,概念!约定!
关于JMM的一些同步的约定︰
1、线程解锁前,必须把共享变量立刻刷回主存。
2、线程加锁前,必须读取主存中的最新值到工作内存中!
3、加锁和解锁是同一把锁
主存和线程缓存的工作原理---8种操作
read--load
use--assign
write--store
lock--unlock
Volatile保证可见性
package VolatileA;
import java.util.concurrent.TimeUnit;
/**volatile保证可见性
* @author liu
*/
public class Demo01 {
//不加 volatile,程序就会死循环
//加volatile,可以保证可见性
private volatile static int num = 0;
public static void main(String[] args) {
new Thread(() -> {
//线程对主内存得到变化不知道
while (num == 0) {
}
;
}).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
num = 1;
System.out.println(num);
}
}
volatile 不保证原子性
package VolatileA;
import java.util.concurrent.atomic.AtomicInteger;
/**
* volatile 不保证原子性..原子性:不可分割
*
* @author liu
*/
public class Demo02 {
private volatile static AtomicInteger num=new AtomicInteger();
//private volatile static int num = 0;//volatile没有用
public static void add() {
//num++;//不是原子性性操作
num.getAndIncrement();//AtomicInteger +1方法,CAS
}
public static void main(String[] args) {
for (int i = 0; i < 300; i++) {
new Thread(() -> {
for (int j = 0; j < 100000; j++) {
add();
}
}).start();
}
while (Thread.activeCount() > 2) {
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+num);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现