原子性
要么全执行,要么都不做
这个比较熟悉,常见的如:
i++
还有32位虚拟机对64位虚拟机中Long型变量的操作也不是原子性的
有序性
-
并发时,程序的执行可能会出现乱序
image.png
image.png
- 一条指令的执行是可以分为很多步骤的
– 取指 IF
– 译码和取寄存器操作数 ID
– 执行或者有效地址计算 EX
– 存储器访问 MEM
– 写回 WB
![](https://img.haomeiwen.com/i10780978/cc2319057ba44e22.png)
来个复杂点的
![](https://img.haomeiwen.com/i10780978/a29babcb32e3e226.png)
![](https://img.haomeiwen.com/i10780978/05522d0f4530cfac.png)
![](https://img.haomeiwen.com/i10780978/f3842e525b0195db.png)
可见性
可见性是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。
– 编译器优化
– 硬件优化(如写吸收,批操作)
![](https://img.haomeiwen.com/i10780978/d09b355f6703f794.png)
- 来看个代码
package someTest;
public class VisibilityTest extends Thread{
private boolean stop;
public void run() {
int i=0;
while(!stop) {
i++;
System.out.println("i="+i);
}
System.out.println("finish loop,i="+i);
}
public void stopIt() {
stop=true;
}
public boolean getStop() {
return stop;
}
public static void main(String[] args) throws InterruptedException {
VisibilityTest v=new VisibilityTest();
v.start();
Thread.sleep(3000);
v.stopIt();
System.out.println("main finish");
System.out.println(v.getStop());
}
}
上面这段代码的意思就是根据标志位stop来决定是不是停止线程运行。看这意思应该是要停,可是真的会停吗?不会的,因为stop是不可见的。这是Java虚拟机层面的可见性问题
但我们加一个volatile修饰符怎么样?
package someTest;
public class VisibilityTest extends Thread{
private volatile boolean stop;
public void run() {
int i=0;
while(!stop) {
i++;
System.out.println("i="+i);
}
System.out.println("finish loop,i="+i);
}
public void stopIt() {
stop=true;
}
public boolean getStop() {
return stop;
}
public static void main(String[] args) throws InterruptedException {
VisibilityTest v=new VisibilityTest();
v.start();
Thread.sleep(3000);
v.stopIt();
System.out.println("main finish");
System.out.println(v.getStop());
}
}
加上之后,由于这个stop标志位是内存可见的了,那么过一会儿,它就停了。
指令重排带来的问题
![](https://img.haomeiwen.com/i10780978/973f18337dec6a73.png)
happen before原则
![](https://img.haomeiwen.com/i10780978/424da43195ee9301.png)
线程安全的概念
指某个函数、函数库在多线程环境中被调用时,能够正确地处理各个线程的局部变量,使程序功能正确完成。
-
i++在多线程访问的情况下
image.png
-
解决
image.png
网友评论