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

Java线程检查非易失性变量的更改似乎要花很长时间

Java线程检查非易失性变量的更改似乎要花很长时间,java,multithreading,volatile,Java,Multithreading,Volatile,如果我在这方面做了坏事,我很抱歉,但我有一个问题是这个问题的衍生: 基本上,我想看看从a变量中删除volatile后会发生什么。以下是原始问题的代码,并应用了我的修改: public class Test { //volatile static private int a; static private int a; static private int b; public static void main(String [] args) throws Exceptio

如果我在这方面做了坏事,我很抱歉,但我有一个问题是这个问题的衍生:

基本上,我想看看从
a
变量中删除
volatile
后会发生什么。以下是原始问题的代码,并应用了我的修改:

public class Test {
    //volatile static private int a;
    static private int a;
    static private int b;
public static void main(String [] args) throws Exception {
    for (int i = 0; i < 100; i++) {
        new Thread() {

            @Override
            public void run() {
                int tt = b; // makes the jvm cache the value of b

                while (a==0) {

                }
                //some threads never get here (past the a==0 loop)

                if (b == 0) {
                    System.out.println("error");
                }
            }

        }.start();
    }

    b = 1;
    a = 1;
}
}
公共类测试{
//易失性静态私有inta;
静态私有inta;
静态私有intb;
公共静态void main(字符串[]args)引发异常{
对于(int i=0;i<100;i++){
新线程(){
@凌驾
公开募捐{
int tt=b;//使jvm缓存的值为b
while(a==0){
}
//有些线程永远不会到达这里(通过a==0循环)
如果(b==0){
System.out.println(“错误”);
}
}
}.start();
}
b=1;
a=1;
}
}
在我的笔记本电脑(Win 7 64,JVM build 1.7.0_04-b22)上发生的事情是,如果没有
volatile
,代码似乎永远运行(保持运行20分钟)。添加更多的控制台输出告诉我,虽然100个线程中的大多数最终都看到了
a
0
1
的变化,但仍然有少数线程(少于10个)继续执行
a==0
循环


我的问题是:这些线程最终也会看到这种变化吗?如果是,与大多数类似的线程相比,花费10秒或数千倍的时间来完成它是否正常?为什么呢?

这与变量的传播速度无关;机器代码可能是这样的:甚至没有尝试内存写入。该值可以驻留在寄存器中

无论如何,我的建议是不要去探究坏掉的Java代码的行为:不管怎样,它总是不同的。相反,学习如何正确编写同步程序。详细研究Java内存模型并理解其保证。JMM的保证与支持这些保证的实际JVM实现代码相去甚远,而JMM是专门为JVM提供应用各种优化的自由而编写的


作为一个特别令人痛心的例子,当解释代码或C1代码被及时替换为C2代码时,被破坏代码的行为可能会在执行过程中发生变化。运行所引用的程序没有什么可学的。

这与变量的传播速度无关;机器代码可能是这样的:甚至没有尝试内存写入。该值可以驻留在寄存器中

无论如何,我的建议是不要去探究坏掉的Java代码的行为:不管怎样,它总是不同的。相反,学习如何正确编写同步程序。详细研究Java内存模型并理解其保证。JMM的保证与支持这些保证的实际JVM实现代码相去甚远,而JMM是专门为JVM提供应用各种优化的自由而编写的


作为一个特别令人痛心的例子,当解释代码或C1代码被及时替换为C2代码时,被破坏代码的行为可能会在执行过程中发生变化。运行所引用的程序没有什么可学的。

每个线程都有自己的本地内存。即使从一个线程对同一变量进行更改,也可能不会(并且您应该假设:不会)传播到其他线程

要在线程之间强制执行内存同步,必须使用
synchronized
块并获取该块中的变量值

实现这一点的最简单方法是使用
Atomic
-类变量,如
AtomicInteger
。它确保原子和数据无竞争地访问它们的值

使用volatile是一个选项,但它会阻止编译器对该变量进行任何优化。此外,它只适用于原子操作,使用它可能会遇到各种竞争条件,使用同步块可以避免这种情况


关于Java内存模型如何实际工作的最精确和详细信息可以在和中找到。对这些文档的各种解释(包括我的)可能是错误的,因此在有疑问时请记住查看可靠的来源。

每个线程都有自己的本地内存。即使从一个线程对同一变量进行更改,也可能不会(并且您应该假设:不会)传播到其他线程

要在线程之间强制执行内存同步,必须使用
synchronized
块并获取该块中的变量值

实现这一点的最简单方法是使用
Atomic
-类变量,如
AtomicInteger
。它确保原子和数据无竞争地访问它们的值

使用volatile是一个选项,但它会阻止编译器对该变量进行任何优化。此外,它只适用于原子操作,使用它可能会遇到各种竞争条件,使用同步块可以避免这种情况


关于Java内存模型如何实际工作的最精确和详细信息可以在和中找到。这些文件的各种解释(包括我的解释)可能是错误的,因此当有疑问时,请记住查看可靠的来源。

考虑将代码放在这里,以防其他问题被删除,并且只是为了有一个独立的问题。请发布代码,人们可能不喜欢浏览其他网站pages@MattiLyra:根据您的要求,我添加了代码段。感谢您的回答和评论,它们都非常有用。我看到大多数人都说,如果不使用volatile,线程会永远挂起,这是正常的