首页 热点专区 小学知识 中学知识 出国留学 考研考公
您的当前位置:首页正文

笔记15(volatile)

2024-12-09 来源:要发发知识网

代码:

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

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

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

显示全文