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 6线程输出不是异步的?_Java_Multithreading_Asynchronous - Fatal编程技术网

Java 6线程输出不是异步的?

Java 6线程输出不是异步的?,java,multithreading,asynchronous,Java,Multithreading,Asynchronous,这段代码应该产生均匀和不均匀的输出,因为在任何方法上都没有同步。然而,JVM上的输出总是均匀的。我真的很困惑,因为这个例子直接来自Doug Lea public class TestMethod implements Runnable { private int index = 0; public void testThisMethod() { index++; index++; System.out.println(Thread.cu

这段代码应该产生均匀和不均匀的输出,因为在任何方法上都没有同步。然而,JVM上的输出总是均匀的。我真的很困惑,因为这个例子直接来自Doug Lea

public class TestMethod implements Runnable {

private int index = 0;

    public void testThisMethod() {
        index++;
        index++;
        System.out.println(Thread.currentThread().toString() + " "
                    + index );

    }

    public void run() {
        while(true) {
            this.testThisMethod();
        }
    }

    public static void main(String args[]) {
        int i = 0;
        TestMethod method = new TestMethod();
        while(i < 20) {
            new Thread(method).start();
            i++;
        }
    }
}
public类TestMethod实现可运行{
私有整数指数=0;
公共void testThisMethod(){
索引++;
索引++;
System.out.println(Thread.currentThread().toString()+“”
+指数);
}
公开募捐{
while(true){
this.testThisMethod();
}
}
公共静态void main(字符串参数[]){
int i=0;
TestMethod=新的TestMethod();
而(i<20){
新线程(方法).start();
i++;
}
}
}
输出 螺纹[螺纹-8,5,主螺纹]135134

螺纹[螺纹-8,5,主螺纹]135136

螺纹[螺纹-8,5,主螺纹]135138

螺纹[螺纹-8,5,主螺纹]135140

螺纹[螺纹-8,5,主螺纹]135142


线程[Thread-8,5,main]135144

您没有将
索引标记为volatile。这意味着编译器可以优化对它的访问,它可能会将您的2个增量合并为一个加法。

您没有将
索引标记为volatile。这意味着编译器可以优化对它的访问,并且它可能会将您的2个增量合并到一个加法中。

您不知道这一点。自动调度的要点是它不能保证。它可能会对运行相同代码的两个线程进行完全不同的处理。或者完全一样。或者完全一样一个小时然后突然变了


问题的关键是,即使你解决了其他答案中提到的问题,你仍然不能依靠事情以特定的方式出现;您必须始终准备好Java内存和线程模型允许的任何可能的交叉,这包括
println
总是在偶数个增量之后发生,即使表面上看起来不太可能发生这种情况。

您不知道这一点。自动调度的要点是它不能保证。它可能会对运行相同代码的两个线程进行完全不同的处理。或者完全一样。或者完全一样一个小时然后突然变了


问题的关键是,即使你解决了其他答案中提到的问题,你仍然不能依靠事情以特定的方式出现;您必须随时准备好Java内存和线程模型允许的任何可能的交叉,这包括
println
总是在偶数个增量之后发生,即使表面上看起来不太可能发生这种情况。

结果正如我所期望的。输出之间的索引将增加两次,并且线程之间没有交互

为了扭转这个问题,你为什么会期望奇数输出


编辑:哎呀。我错误地假设每个线程都创建了一个新的runnable,因此每个线程都有一个不同的索引,而不是共享索引。令人不安的是,这样一个有缺陷的答案竟然获得了3张赞成票……

结果正是我所期望的。输出之间的索引将增加两次,并且线程之间没有交互

为了扭转这个问题,你为什么会期望奇数输出


编辑:哎呀。我错误地假设每个线程都创建了一个新的runnable,因此每个线程都有一个不同的索引,而不是共享索引。令人不安的是,这样一个有缺陷的答案是如何获得3票赞成票的…

首先:正如其他人所指出的,根本不能保证线程在两个增量操作之间会被中断

请注意,打印到
System.out
很可能会强制线程进行某种同步,因此当线程从中返回时,它们很可能刚刚开始一个时间片,因此它们可能会完成两个递增操作,然后等待
System.out
的共享资源

尝试将
System.out.println()替换为如下内容:

int snapshot = index;
if (snapshot % 2 != 0) {
  System.out.println("Oh noes! " + snapshot);
}

首先:正如其他人所指出的,根本不能保证线程在两个增量操作之间会被中断

请注意,打印到
System.out
很可能会强制线程进行某种同步,因此当线程从中返回时,它们很可能刚刚开始一个时间片,因此它们可能会完成两个递增操作,然后等待
System.out
的共享资源

尝试将
System.out.println()替换为如下内容:

int snapshot = index;
if (snapshot % 2 != 0) {
  System.out.println("Oh noes! " + snapshot);
}

我尝试了
volatile
,得到了以下结果(使用
if
仅在奇数时打印):


回复评论:

索引实际上是共享的,因为我们有一个
TestMethod
实例,但有许多
Thread
s在我们现有的
TestMethod
实例上调用
testThisMethod()


代码(除上述内容外无任何更改):

public class TestMethod implements Runnable {

    volatile private int index = 0;

        public void testThisMethod() {
            index++;
            index++;
            if(index % 2 != 0){
            System.out.println(Thread.currentThread().toString() + " "
                        + index );
            }

        }

        public void run() {
            while(true) {
                this.testThisMethod();
            }
        }

        public static void main(String args[]) {
            int i = 0;
            TestMethod method = new TestMethod();
            while(i < 20) {
                new Thread(method).start();
                i++;
            }
        }
    }
public类TestMethod实现可运行{
易失性私有int指数=0;
公共void testThisMethod(){
索引++;
索引++;
如果(索引%2!=0){
System.out.println(Thread.currentThread().toString()+“”
+指数);
}
}
公开募捐{
while(true){
this.testThisMethod();
}
}
公共静态void main(字符串参数[]){
int i=0;
TestMethod=新的TestMethod();
而(i<20){
新线程(方法).start();
i++;
}
}
}

我尝试了
volatile
,得到了以下结果(w