Java程序输出 - 并发

时间:2010-08-14 12:17:02

标签: java concurrency

这可能是一个愚蠢的问题但是,这个程序的输出(它的方式)可以为零吗?

public class Test2{

    int a = 0;
    AtomicInteger b = new AtomicInteger();
    public static Test2  c = new Test2();

    public static void main(String[] args){

        Thread t1 = new Thread(new MyTest1());
        Thread t2 = new Thread (new Mytest2());

        t1.start();
        t2.start();
    }

}

class MyTest1 implements Runnable{

    public void run(){
        Test2.c.a = 1;
        Test2.c.b.compareAndSet(0,1);

    }
}

class Mytest2 implements Runnable{
    public void run(){
        int x = 0;

        if(Test2.c.b.get() == 1)
            x = Test2.c.a;

        System.out.println("Value of x = "+x);
    }

}

我问这个的原因是,虽然我正在使用AtomicInteger,但MyTest2中的if()语句可能先执行,然后x的值为zero..right?

或者我没有直接思考。

任何帮助都将受到高度赞赏。

2 个答案:

答案 0 :(得分:5)

  

这个程序的输出(它的方式)是零吗?

是的,这是可能的。代码不保证t1t2完成之前完成任何方式。如果这是您的意图,您可能会发现CountdownLatchCyclicBarrier有用。单击链接,它们的javadocs包含代码示例。


那就是说,我宁愿传递AtomicInteger的引用作为两个runnables的构造函数参数,而不是以静态方式访问它。

答案 1 :(得分:1)

通过一个小的更改,可以保证输出为1

public void run(){
    int x = 1;

    if(Test2.c.b.get() == 1)
        x = Test2.c.a;

    System.out.println("Value of x = "+x);
}

由于易失性读/写的排序保证:

  • x最初是1
  • 可以分配给x的唯一其他值是Test2.c.a
  • 的值 只有先前从Test2.c.a 读取了x,才能将
  • 1复制到Test2.c.b 仅在将1写入Test2.c.b
  • 1写入Test2.c.a
  • 因为Test2.c.b是易失性的,所以读取它的任何线程也会通过写入Test2.c.b的同一线程观察所有先前对所有变量(易失性或非易失性)的写入。这意味着t2也会看到1写入Test2.c.a
  • 如果测试失败(即读取Test2.c.b返回1以外的内容),则x保留其初始值1,因此输出仍为1

我怀疑这是该计划的作者试图说明的内容,0的默认值x是一个错字。