Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.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_Synchronization_Volatile - Fatal编程技术网

Java 为什么线程在不同的运行方法体中表现不同?

Java 为什么线程在不同的运行方法体中表现不同?,java,multithreading,synchronization,volatile,Java,Multithreading,Synchronization,Volatile,这段代码来自有效的Java(第66项):(没有同步或易失性,这永远不会结束) 正如Bloch在那一章中提到的,它永远不会向控制台写入“finished”。我一直在使用这个类,并将该行添加到runnable run方法中: System.out.println("im still running"); 有了这个,while循环不仅增加i,而且在每个循环中打印出这个字符串。但让我疯狂的是,当主线程从睡眠中恢复时,线程会在1秒钟后停止 修改:(停止而不进行易失性/同步) 那么这背后的逻辑是什么呢?将

这段代码来自有效的Java(第66项):(没有同步或易失性,这永远不会结束)

正如Bloch在那一章中提到的,它永远不会向控制台写入“finished”。我一直在使用这个类,并将该行添加到runnable run方法中:

System.out.println("im still running");
有了这个,while循环不仅增加i,而且在每个循环中打印出这个字符串。但让我疯狂的是,当主线程从睡眠中恢复时,线程会在1秒钟后停止

修改:(停止而不进行易失性/同步)


那么这背后的逻辑是什么呢?

将数据写入控制台通常是通过线程安全操作实现的

在这种情况下,您向控制台写入数据的行为也会触发更新
canrunstatic
变量,如您的
backgroundThread
所示


请注意,Java内存模型和Java
系统的实现都没有承诺这一点。确切地说,线程停止并不保证线程会停止,但它不会被禁止。这背后的逻辑由提供,这是一个相当复杂的主题,但需要了解Java中的多线程

其概念是,如果一个线程的非易失性字段的写入操作与另一个线程同步,那么另一个线程只需要看到该字段。如果在其中执行的线程所显示的行为没有更改,则允许编译器对某些操作重新排序。但另一个线程可能会看到这一点。因此,您需要进行适当的同步,以便告诉编译器某些部分不允许重新排序


请在此处阅读有关此问题的全文:

内存模型中未指定此选项。写入控制台是JMM中的一个外部操作,但这不能保证同步,也不能创建与edge的同步。所以这不是对背后逻辑的解释。好的一点,这是原因,但不要求它发生。我更新了答案以反映这一点。
System.out.println("im still running");
public class ThreadPractice {
static boolean canrunstatic;


public static void main(String[] args) throws InterruptedException {

    Thread backgroundThread = new Thread(new Runnable() {
        public void run() {
            int i = 0;
            while (!canrunstatic){i++;System.out.println("im still running");}
            System.out.println("finished");
        }
    });
    backgroundThread.start();
    TimeUnit.SECONDS.sleep(1);
    canrunstatic = true;


}