目录
一、什么是线程安全?
二、线程不安全的原因
1、线程调度是随机的
2、修改共享数据:多个线程修改同⼀个变量
3、原⼦性 编辑
(1)什么是原⼦性
(2)⼀条 java 语句不⼀定是原⼦的,也不⼀定只是⼀条指令
(3)不保证原⼦性会给多线程带来什么问题
(4)可⻅性:可⻅性指, ⼀个线程对共享变量值的修改,能够及时地被其他线程看到.
(5)Java 内存模型 (JMM)
1) 初始情况下, 两个线程的⼯作内存内容⼀致.
编辑 2) ⼀旦线程1 修改了 a 的值, 此时主内存不⼀定能及时同步. 对应的线程2 的⼯作内存的 a 的值也不⼀定能及时同步.
此时引⼊了两个问题:
1) 为啥整这么多内存?
2) 为啥要这么⿇烦的拷来拷去?
4、指令重排序
引言:
在 Java 编程中,线程安全是一个至关重要的概念。当多个线程同时访问共享的资源时,如果没有适当的同步措施,就会出现数据竞争和不一致的情况,从而导致程序出现各种难以预料的错误。因此,理解并处理线程安全问题是编写高质量、可靠性强的 Java 程序的关键。
一、什么是线程安全?
线程安全是指在多线程环境中,对共享资源的访问不会导致数据的损坏或不一致。一个线程安全的程序在多线程环境下执行时,能够确保各个线程都能正确地操作共享的数据,而不会产生意外结果。
二、线程不安全的原因
1、线程调度是随机的
2、修改共享数据:多个线程修改同⼀个变量
3、原⼦性
(1)什么是原⼦性
(2)⼀条 java 语句不⼀定是原⼦的,也不⼀定只是⼀条指令
- 从内存把数据读到 CPU
- 进⾏数据更新
- 把数据写回到 CPU
(3)不保证原⼦性会给多线程带来什么问题
(4)可⻅性:可⻅性指, ⼀个线程对共享变量值的修改,能够及时地被其他线程看到.
(5)Java 内存模型 (JMM)
- 线程之间的共享变量存在 主内存 (Main Memory).
- 每⼀个线程都有⾃⼰的 "⼯作内存" (Working Memory) .
- 当线程要读取⼀个共享变量的时候, 会先把变量从主内存拷⻉到⼯作内存, 再从⼯作内存读取数据
- 当线程要修改⼀个共享变量的时候, 也会先修改⼯作内存中的副本, 再同步回主内存.
1) 初始情况下, 两个线程的⼯作内存内容⼀致.
2) ⼀旦线程1 修改了 a 的值, 此时主内存不⼀定能及时同步. 对应的线程2 的⼯作内存的 a 的值也不⼀定能及时同步.
这个时候代码中就容易出现问题.
此时引⼊了两个问题:
- 为啥要整这么多内存?
- 为啥要这么⿇烦的拷来拷去?
1) 为啥整这么多内存?
2) 为啥要这么⿇烦的拷来拷去?
那么接下来问题⼜来了, 既然访问寄存器速度这么快, 还要内存⼲啥??
值的⼀提的是, 快和慢都是相对的. CPU 访问寄存器速度远远快于内存, 但是内存的访问速度⼜远远快 于硬盘. 对应的, CPU 的价格最贵, 内存次之, 硬盘最便宜
4、指令重排序
- 去前台取下 U 盘
- 去教室写 10 分钟作业
- 去前台取下快递
编译器对于指令重排序的前提是 "保持逻辑不发⽣变化". 这⼀点在单线程环境下⽐较容易判断, 但是在多线程环境下就没那么容易了, 多线程的代码执⾏复杂程度更⾼, 编译器很难在编译阶段对代码的执⾏效果进⾏预测, 因此激进的重排序很容易导致优化后的逻辑和之前不等价.
总结:
在编写 Java 程序时,必须时刻牢记线程安全问题,合理使用同步机制、并发容器和原子类等工具,确保多线程环境下程序的正确性和稳定性。只有这样,才能编写出高效、健壮的多线程应用。