代码:
public class Main {
public static void main(String[] args) throws InterruptedException {
MyThread<Integer> t = new MyThread<Integer>();
System.out.println("========开始执行========");
new Thread(t).start();
System.out.println("执行到这了F1");
t.isEnd();
System.out.println("执行到这了F3");
}
}
class MyThread<V> implements Runnable {
public boolean flag = false;
@Override
public void run() {
int t = 0;
for (int n = 1; n <= 5; n++) {
System.out.println(n);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
t += n;
}
System.out.println("总和:"+t);
System.out.println("更新flag值!!!");
flag = true;
}
public void isEnd() throws InterruptedException {
while (true) {
// System.out.println("执行到这了F2");
if (this.flag) {
System.out.println("=========执行完毕========");
break;
}
}
}
}
上面代码执行结果是如下,从程序上来看由于线程间的不可见性,运行起来就进入了一个死循环。
这里可以通过volatile使共享变量在线程间保持可见性,解决上面的问题,volatile有同步作用,可以强制将修改后的共享变量推送给所有线程,volatile修饰的基本类型变量在读取时可以保证变量值是最新的(但不保证原子性)。
在while(true)循环中加一行代码: System.out.println("执行到这了F2");
程序在循环n次之后正常结束了。
从以上输出结果看,子线程在执行完for循环后修改了flag值,回写给主内存,isEnd方法所在线程也拿到了共享变量修改后的值。
另:或者加上Thread.sleep(100);也可以正常结束。
不同线程对共享变量是相互不可见的,通常可以使用volatile和Synchronized来实现可见性
事实上非短时间内高并发的情况下,即使没有保证可见性的措施,很多时候共享变量依然能够在主内存和工作内存间得到及时的更新。
最后还有一个问题,为什么不加上一段输出语句线程间共享变量就没办法刷新。
网友评论