Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程:解释为什么不总是打印变量的最新值_Java_Multithreading - Fatal编程技术网

Java线程:解释为什么不总是打印变量的最新值

Java线程:解释为什么不总是打印变量的最新值,java,multithreading,Java,Multithreading,我使用Java线程编写了以下代码: public class ThreadExample implements Runnable{ public Thread thread; static int i = 0; ThreadExample(){ thread = new Thread(this); thread.start(); } public static void main(String[] args) {

我使用Java线程编写了以下代码:

public class ThreadExample implements Runnable{

    public Thread thread;
    static int i = 0;
    ThreadExample(){
        thread = new Thread(this);
        thread.start();
    }

    public static void main(String[] args) {
        ThreadExample example = new ThreadExample();
        for(int n =0; n<1000; n++){
            System.out.println("main thread "+i);
            i++;
        }
    }

    public void run(){
        for(int index=0; index<1000; index++){
            System.out.println("Sub thread "+i);
            i++;
        }
    }
}
我知道运行的线程不遵循其顺序。但是,我不明白的是:为什么主线程打印1(它打印变量I),而变量I已经到了12?(因为子线程已打印到12)


谢谢:)

最有可能的解释是,文本准备打印和实际打印之间有很大的延迟。主线程准备语句“main thread 1”,然后必须等待子线程释放
System.out
上的锁,然后获取锁,以便实际打印它


如果你让
i
变得不稳定,并且这种情况仍然存在,那么这几乎是唯一的解释。

最有可能的解释是,文本准备打印到实际可以打印之间有很大的延迟。主线程准备语句“main thread 1”,然后必须等待子线程释放
System.out
上的锁,然后获取锁,以便实际打印它


如果你让
i
不稳定,并且这种情况仍然发生,那么这几乎是唯一的解释。

据我所知,这是因为
系统的缓冲。out

每次打印后,尝试写入文件或调用
System.out.flush()

并尝试通过同步方法增加
i

public synchronized void increment() {
  i++;
}

据我所知,这是因为
System.out

每次打印后,尝试写入文件或调用
System.out.flush()

并尝试通过同步方法增加
i

public synchronized void increment() {
  i++;
}

这是因为如果没有一些同步或
volatile
关键字,线程将看不到彼此的修改


请参见

发生这种情况的原因是,如果没有一些同步或
volatile
关键字,线程将看不到彼此的修改


请参见

结果可能是由于锁获取方式(在System.out.println调用的掩护下发生)本身并不公平。不公平的实现,或者至少是部分不公平的实现,通常不能保证线程将以等待锁的相同顺序获得锁

结果是,当两个线程在紧循环中重复竞争锁时(如在您的示例中),通常会有一个线程执行一次采集,然后是另一个线程执行一次采集,依此类推。不公平的锁通常更容易实现,并且通常比完全公平的高争用锁更能提高性能(吞吐量),因为它们不会受到影响。很明显,缺点是不能保证特定等待线程获得锁的顺序,理论上,某些等待线程可能会被饿死(在实践中,这可能不会发生,或者当某些线程已经等待了不寻常的时间时,锁可能被设计为回退到公平行为)

给定不公平的锁,关于的模式是自然的。第二个线程中的循环获得了锁,在第一个线程读取1并开始等待后不久,此时要输出的字符串已与前导文本连接,因此值1为“baked in”。主线程必须等待另一个线程上的多个锁定/解锁对,在该对上它有机会运行,并打印旧值


另一种解释是,由于缺少volatile,解释器或JIT甚至不再读取i的共享值,但是将变量托管到寄存器中-这在JMM和JVM规范下是允许的,因为没有可能修改i的干预方法。

结果可能是由于锁获取(在System.out.println调用的封面下发生)本身并不公平。不公平的实现,或者至少是部分不公平的实现,通常不能保证线程将以等待锁的相同顺序获得锁

结果是,当两个线程在紧循环中重复竞争锁时(如在您的示例中),通常会有一个线程执行一次采集,然后是另一个线程执行一次采集,依此类推。不公平的锁通常更容易实现,并且通常比完全公平的高争用锁更能提高性能(吞吐量),因为它们不会受到影响。很明显,缺点是不能保证特定等待线程获得锁的顺序,理论上,某些等待线程可能会被饿死(在实践中,这可能不会发生,或者当某些线程已经等待了不寻常的时间时,锁可能被设计为回退到公平行为)

给定不公平的锁,关于的模式是自然的。第二个线程中的循环获得了锁,在第一个线程读取1并开始等待后不久,此时要输出的字符串已与前导文本连接,因此值1为“baked in”。主线程必须等待另一个线程上的多个锁定/解锁对,在该对上它有机会运行,并打印旧值


另一种解释是,由于缺少volatile,解释器或JIT甚至不再读取i的共享值,而是将变量托管到寄存器中——这在JMM和JVM规范下是允许的,因为没有可能修改i的干预方法。

我尝试过,但结果没有改变。它不是按递增顺序打印的。尝试了无缓冲系统。错误?我尝试过,但结果没有改变。它不是按递增顺序打印的。尝试了无缓冲系统。改为出错?@fge我使用了volatile,但问题仍然存在:(@fge我使用了volatile,但问题是