笔记15(volatile)

作者: 林深见鹿x | 来源:发表于2019-01-21 21:59 被阅读12次

    代码:

    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来实现可见性

    事实上非短时间内高并发的情况下,即使没有保证可见性的措施,很多时候共享变量依然能够在主内存和工作内存间得到及时的更新。

    最后还有一个问题,为什么不加上一段输出语句线程间共享变量就没办法刷新。

    相关文章

      网友评论

        本文标题:笔记15(volatile)

        本文链接:https://www.haomeiwen.com/subject/fyohjqtx.html