显示Java中volatile变量和常用变量之间的差异

显示Java中volatile变量和常用变量之间的差异,java,variables,volatile,Java,Variables,Volatile,我试图创建一个示例来显示volatile变量和普通变量之间的差异,如: package main; public class TestVolatile extends Thread { public int l = 5; public volatile int m = -1; public TestVolatile(String str) { super(str); } public void run() { int

我试图创建一个示例来显示volatile变量和普通变量之间的差异,如:

package main;

public class TestVolatile extends Thread {

    public int l = 5;
    public volatile int m = -1;

    public TestVolatile(String str) {
        super(str);
    }

    public void run() {
        int i = 0;
        while ((l > 1) && (l < 10)) {
            if (m >= 0) {
                m++;
            }
            i++;
            l = 5;
            System.out.println("5=" + i + " m=" + m);
        }

    }

    public static void main(String[] args) throws InterruptedException {
        TestVolatile tva = new TestVolatile("ThreadA");

        tva.start();
        sleep(5);
        synchronized (tva) {
            tva.m = 5;
            tva.l = 10;
        }
    }

}
所以现在变量必须是相同的!但事实并非如此

x: 346946234 y: 346946250
x: 346946418 y: 346946422
x: 346946579 y: 346946582
x: 346946742 y: 346946745
x: 346946911 y: 346946912

您正在同步主线程和测试线程。因此,Java保证使其他线程执行的任何更改可见

顺便说一句,不可能构造一个明确显示易失性和非易失性之间差异的示例。你所能希望的最好是得到一个程序,它以相当高的概率显示差异。如果线程在同一内核上交错运行。你根本无法表现出任何不同

以下程序在我的计算机上显示了易失性变量和非易失性变量之间的差异

public class ShowVolatile {

    final static int NUM_THREADS = 1;

    int x = 0;
    volatile int y = 0;

    public static void main(String... args) {

        final ShowVolatile sv = new ShowVolatile();

        for (int i=0; i< NUM_THREADS; i++) {
            new Thread(new Runnable() {
                public void run() {
                    while (true) {
                        sv.x += 1;    
                        sv.y += 1;    
                    }
                }
            }).start();
        }


        while (true) {
            System.out.println("x: " + sv.x + " y: " + sv.y);
        }
    }

}
公共类ShowVolatile{
最终静态int NUM_线程=1;
int x=0;
挥发性int y=0;
公共静态void main(字符串…参数){
最终ShowVolatile sv=新的ShowVolatile();
对于(inti=0;i

如果增加线程数,将看到更多的同步未命中。但是线程数为1就足够了。至少在我的硬件上有一个四核i7。

让多个线程在volatile变量上执行并发的非同步
++
,应该会有所帮助。然而,它永远不会是确定性的。这可能还取决于底层操作系统和CPU。

我在回答中添加了一个程序,这可能会显示出差异。可能相关:谢谢。当设置NUM_线程时,例如15个差异增加。总是比平常更易波动的变量,因为平常总是丢失。但是System.out.println(“x:+sv.x+”y:+sv.y”);假设不正确,因为可能是主线程在线程递增sv.y之后读取sv.x,在读取sv.y并打印之后读取sv.x。@user710818:是的,但这只能解释1的差异。你会考虑接受这个答案吗?
public class ShowVolatile {

    final static int NUM_THREADS = 1;

    int x = 0;
    volatile int y = 0;

    public static void main(String... args) {

        final ShowVolatile sv = new ShowVolatile();

        for (int i=0; i< NUM_THREADS; i++) {
            new Thread(new Runnable() {
                public void run() {
                    while (true) {
                        sv.x += 1;    
                        sv.y += 1;    
                    }
                }
            }).start();
        }


        while (true) {
            System.out.println("x: " + sv.x + " y: " + sv.y);
        }
    }

}