demo1
package com.entity;
public class Test01 {
private static boolean flag;
public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
while(true){
if (flag == !flag) {
System.out.println("==over==");
System.exit(0);
}
}
}
}.start();
Thread.sleep(1);
new Thread() {
@Override
public void run() {
while (true) {
flag = !flag;
}
}
}.start();
}
}
该方式下运行 System.out.println("==over=="); 永远不会执行进入了死循环
public class Test02 {
private static volatile boolean flag;
public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
while(true){
if (flag == !flag) {
System.out.println("==over==");
System.exit(0);
}
}
}
}.start();
Thread.sleep(1);
new Thread() {
@Override
public void run() {
while (true) {
flag = !flag;
}
}
}.start();
}
}
该方式下运行 System.out.println("==over=="); 打印
demo2
public class Test03 {
private static boolean keepRunning=true;
public static void main(String[] args) throws Exception {
new Thread(
@override
public void run{
while (keepRunning){
//System.out.println("========");;
}
}
).start();
Thread.sleep(1000);
keepRunning=false;
}
}
同样 永远死循环
public class Test04 {
private static volatile keepRunning=true;
public static void main(String[] args) throws Exception {
new Thread(
@override
public void run{
while (keepRunning){
System.out.println("========");
}
}
).start();
Thread.sleep(1000);
keepRunning=false;
}
}
把注释打开 System.out.println("========"); 执行程序结束 怎么跟内存不可见对应不上呢?
参见:https://www.cnblogs.com/wenjieyatou/p/6210189.html 是由于 打印语句触发了happen—before
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!isStopRequested()) {
i++;
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);//1秒
requestStop();
}
}
此种情况下还是始终死循环 因为i++ 没有触发happen—before
出现死循环的原因:
java 内存模型(JMM)有主内存和线程的工作内存 关系如下:
1. 线程的工作内存会去读取主内存的成员变量并保存副本
2. 线程在工作内存中修改副本
3. 将修改后的副本的值推送给主空间并改写主空间该成员变量的值(线程栈执行完毕后会把副本的值推送给主存)
4. 主空间成员变量修改后的值将不会主动推送给其他线程, 这就造成了线程的工作内存的共享变量的不同步
就是造成上面死循环的原因
如何解决呢?
通过 volatile 解决
Volatile字段主要用于线程之间进行通信,volatile字段的每次读行为都能看到其它线程最后一次对该字段的写行为,所以共享变量的数据是最新的
参考文章:
http://www.cnblogs.com/huangleshu/p/10026222.html
https://baijiahao.baidu.com/s?id=1595082600371869908&wfr=spider&for=pc
static 是内存中的唯一份共享变量 volatile 也是内存唯一份的内存可见 那么二者有和区别呢?
1. volatile是告诉编译器,每次取这个变量的值都需要从主存中取,而不是用自己线程工作内存中的缓存.
2. static 是说这个变量,在主存中所有此类的实例用的是同一份,各个线程创建时需要从主存同一个位置拷贝到自己工作内存中去(而不是拷贝此类不同实例中的这个变量的值),
也就是说只能保证线程创建时,变量的值是相同来源的,运行时还是使用各自工作内存中的值,依然会有不同步的问题.
参考:http://www.cnblogs.com/cvbaka/p/4764503.html