为什么这个坏程序总是运行? [英] Why this broken program always runs?

查看:90
本文介绍了为什么这个坏程序总是运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用JCIP中的示例,但以下程序不应运行,但是即使我执行它说20次也可以正常工作,这意味着readynumber在这种情况下也变得可见

I was trying examples from JCIP and Below program should not work but even if I execute it say 20 times it always work which means ready and number are becoming visible even if it should in this case

public class NoVisibility {
private static boolean ready;
private static int number;

private static class ReaderThread implements Runnable {
    public void run() {
        while (!ready)
            Thread.yield();
        System.out.println(number);
    }
}

public static void main(String[] args) {
    System.out.println(Runtime.getRuntime().availableProcessors());
    //Number of Processor is 4 so 4+1 threads
    new Thread(new ReaderThread()).start();
    new Thread(new ReaderThread()).start();
    new Thread(new ReaderThread()).start();
    new Thread(new ReaderThread()).start();
    new Thread(new ReaderThread()).start();

    number = 42;
    ready = true;
}
}

在我的机器上,它总是打印

On my machine it always prints

4 -- Number of Processors
42
42
42
42
42

According to Listing 3.1 of JCIP It should sometimes print 0 or should never terminate it also suggest that there is no gaurantee that ready and number written by main thread will be visible to reader thread

更新 在使所有线程仍保持相同的输出后,我在主线程中添加了1000ms睡眠.我知道程序已损坏,我希望它的行为如此

Update I added 1000ms sleep in main thread after strating all threads still same output.I know program is broken And I expect it behave that way

推荐答案

此程序已损坏,因为readynumber应该声明为volatile.
由于readynumber是原始变量,因此对它们的操作是原子性的,但是但不能保证确保它们在其他线程中可见.
似乎调度程序在之后 main之后运行线程,这就是为什么他们看到numberready被初始化的原因.但这只是一个调度.
如果您添加例如main中的sleep以影响调度程序,您将看到不同的结果.
因此,本书是正确的,因为不能将变量未声明为volatile,所以不能保证在单独线程中运行的Runnable是否会看到变量的更新.

This program is broken since ready and number should be declared as volatile.
Due to the fact that ready and number are primitive variables, operations on them are atomic but it is not guaranteed that they will be visible by other threads.
It seems that the scheduler runs the threads after main and that is why they see the number and ready being initialized. But that is just one scheduling.
If you add e.g. a sleep in main so as to affect the scheduler you will see different results.
So the book is correct, there is no guarantee whether the Runnables running in separate threads will ever see the variable's being updated since the variables are not declared as volatile.

更新:
这里的问题是,由于缺少volatile,编译器可以自由读取字段ready一次,并在每次循环执行中重用缓存的值.
该程序具有固有的缺陷.由于线程问题,通常在将应用程序部署到现场时会出现问题. 来自 JSL :

Update:
The problem here is that the due to the lack of volatile the compiler is free to read the field ready just once, and reuse the cached value in each execution of the loop.
The program is inherently flawed. And with threading issues the problem usually appears when you deploy your application to the field.... From JSL:

例如,在下面的(破碎)代码片段中,假定 this.done是一个非易失性布尔字段:

For example, in the following (broken) code fragment, assume that this.done is a non-volatile boolean field:

同时(!this.done)
Thread.sleep(1000);

while (!this.done)
Thread.sleep(1000);

编译器可以自由读取一次this.done字段,然后重用 每次执行循环时的缓存值.这意味着 即使其他线程更改了该循环,循环也永远不会终止 this.done的值.

The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if an other thread changed the value of this.done.

这篇关于为什么这个坏程序总是运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆