volatile

volatile关键字使得变量具有可见性, 可见性变量具有这样的属性: 一个线程对该变量的修改会马上对别的线程可见.语言规范对线程的约束要宽松很多,只要保证线程在退出临界区(同步块)之后,修改的变量的新值对其他线程可见.

拿下面的代码来说,Data中的value成员变量如果不加volatile关键字,那么可能要等到修改value的writer线程退出synchronized同步块之后,reader线程读到的值才是1;而加了volatile修饰之后就能保证,在writer线程执行了this.value=value之后

reader线程读到的value的值就是1.当然事实上很多java虚拟机在实现上做了很多优化,即不必等到writer退出synchronized同步块value的新值就已经对其他线程可见了.不过加了volatile关键字之后就能完全确保这一点.

volatile关键字示例:

public class VolatileDemo {

    static Data data = new Data();
    
    public static void main(String[] args) throws Exception {
        Thread reader = new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println(data.getValue());
            }
        });
        
        Thread writer = new Thread(new Runnable(){
            @Override
            public void run() {
                data.setValue(1);
            }
        });
        
        writer.start();
        Thread.sleep(200);
        reader.start();
    }

    static class Data {
        private volatile int value;

        public void setValue(int value) {
            synchronized (this) {
                System.out.println("before update...");
                this.value = value;
                System.out.println("after update...");
                
                //耗时操作
                for(long i=0; i < Long.MAX_VALUE; i++) {
                    for(long j=0; j < 1; j++) {
                        long v = i*j;
                    }
                }
            }
        }
        public int getValue() {
            return this.value;
        }
    }
}

另一个示例:

public class PrintString implements Runnable {

    private boolean isContinuePrint = true;

    public boolean isContinuePrint() {
        return isContinuePrint;
    }

    public void setContinuePrint(boolean isContinuePrint) {
        this.isContinuePrint = isContinuePrint;
    }

    public void printStringMethod() {
        try {
            while (isContinuePrint) {
                System.out.println("run printStringMethod threadName=" + Thread.currentThread().getName());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        printStringMethod();
    }
}

public class Run {

    public static void main(String[] args) {
        PrintString p = new PrintString();
        new Thread(p).start();
        p.setContinuePrint(false);
    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>