美文网首页
Volatile、Static、Synchronized的可见性

Volatile、Static、Synchronized的可见性

作者: 冰鱼飞鸟 | 来源:发表于2018-06-25 21:55 被阅读0次

    1.Static并不能保证在各个线程中值的一致,因为每个线程有自己的工作内存,工作内存中的变量值是主内存中的拷贝,没有重新从主内存中加载时,并不能知道别的线程对这个变量做了什么修改。

        public static boolean isRun = true;
        public static void main(String[] args) throws InterruptedException {
            Thread1 t1 = new Thread1(1);
            t1.start();
            
            Thread.sleep(1000);
            isRun = false;
            System.err.println("--------stop");;
        }
        
        static class Thread1 extends Thread{
            private int flag;
            public Thread1(int flag) {
                this.flag = flag;
            }
            
            @Override
            public void run() {
                super.run();
                while(true) {
                    if(!isRun) {
                        System.err.println(flag+"," + isRun);
                        break;
                    }
                }
            }
        }
    

    结果如下

    --------stop

    结果是stop已经打印出来,线程中的循环结束不了,因为线程的工作内存中的isRun值还是true,并没有重新从主内存中获取修改后的值。

    2.Volatile,java内存模型保证volatile修饰的变量在各个线程中保持一致,即可见性保证。当一个线程修改了该变量的值,修改后的值可以立即被其他线程获取到。
    (ps:普通变量的值如果要在线程间传递要通过主内存做过渡,及A线程要把修改后的值同步回主内存,B线程要从主内存中获取才能获得普通变量的新值。)
    (ps: Volatile保证可见性,并不能保证对volatile的所有操作都是线程安全,这还要考虑操作的原子性,如volatile int i; i++;并不是原子操作,靠volatile不能保证其线程安全。)

    将上面例子中的isRun加上volatile修饰。

    public static volatile boolean isRun = true;
    //  public static boolean isRun = true;
        public static void main(String[] args) throws InterruptedException {
            Thread1 t1 = new Thread1(1);
            t1.start();
            
            Thread.sleep(1000);
            isRun = false;
            System.err.println("--------stop");;
        }
        
        static class Thread1 extends Thread{
            private int flag;
            public Thread1(int flag) {
                this.flag = flag;
            }
            
            @Override
            public void run() {
                super.run();
                while(true) {
                    if(!isRun) {
                        System.err.println(flag+"," + isRun);
                        break;
                    }
                    
                }
            }
        }
    

    结果如下

    --------stop
    1,false

    3.Synchronized 在保证互斥的同时,还可以保证可见。在进入同步代码块时会使当前线程的工作内存失效,强制从主内存重新获取。
    所以如第一个例子在线程中加上synchronized代码块时

    public static boolean isRun = true;
        public static void main(String[] args) throws InterruptedException {
            Thread1 t1 = new Thread1(1);
            t1.start();
            
            Thread.sleep(1000);
            isRun = false;
            System.err.println("--------stop");;
        }
        
        static class Thread1 extends Thread{
            private int flag;
            public Thread1(int flag) {
                this.flag = flag;
            }
            
            @Override
            public void run() {
                super.run();
                while(true) {
                    if(!isRun) {
                        System.err.println(flag+"," + isRun);
                        break;
                    }
                    //System.err.println("thread is running.");
                    synchronized ("") {
                    }
                    
                }
            }
        }
    

    结果如下

    --------stop
    1,false

    另外一点在测试中发现的是,其实在线程中System.....print和加同步代码块是一样的效果。看System....print的源码,其实就是synchronized。

    public void println(String x) {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    

    相关文章

      网友评论

          本文标题:Volatile、Static、Synchronized的可见性

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