我还是没搞懂VOLATILE是干什么用的。另外JAVA的堆,栈概念我懂,这个跟主内存,工作内存又有什么不一样?下面有个小代码:
public class mythread extends Thread {
boolean stop=false;//我这里不用VOLATIEL修饰符,照样也能起作用,这是为什么?
public void run(){
while(!stop){
System.out.println("hello");
} }
public void setStop(boolean st){
stop=st;
}
}
什么样的变量应该用volatile修饰??如果是为了各个线程都能使用,那为什么不用static 来代替volatile?
public class mythread extends Thread {
boolean stop=false;//我这里不用VOLATIEL修饰符,照样也能起作用,这是为什么?
public void run(){
while(!stop){
System.out.println("hello");
} }
public void setStop(boolean st){
stop=st;
}
}
什么样的变量应该用volatile修饰??如果是为了各个线程都能使用,那为什么不用static 来代替volatile?
同步的代价, 主要由其覆盖范围决定, 如果可以降低同步的覆盖范围, 则可以大幅提升程序性能. 而volatile的覆盖范围仅仅变量级别的. 因此它的同步代价很低.volatile原理是什么?
volatile的语义, 其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.(工作内存详见java内存模型)因此, 当多核或多线程在访问该变量时, 都将直接操作主存, 这从本质上, 做到了变量共享.volatile的有什么优势?
1, 更大的程序吞吐量
2, 更少的代码实现多线程
3, 程序的伸缩性较好
4, 比较好理解, 无需太高的学习成本volatile有什么劣势?
1, 容易出问题
2, 比较难设计
我认为老紫竹说得部分是对的,部分说得是不对的。
volatile是阻止编译器优化用的关键字。但是不能根除线程不安全的情况,具体详情看《Windows核心编程》。
书中的例子会告诉你为什么会出现线程不安全的情况,也就知道了,为什么用了volatile也不能防止线程不安全的情况出现。
原因就是内存和寄存器(这里是JVM的模拟寄存器)之间的指令穿插问题引发的。volatile只是告诉JVM要从内存取数据,而不是从寄存器取数据,因为,内存数据可能被其他的Thread所改变。但是这个不能改变线程不安全的情况。具体为什么,我就不写ASM或者ByteCode了。至于老紫竹说的同步,我就更不能认同了,这个关键字和synchronized没有关系的。有机会我们讨论synchronized,实际这个和同步关系也不大。