Вывод программы Java - одновременный - PullRequest
3 голосов
/ 14 августа 2010

Возможно, это глупый вопрос, но может ли результат этой программы (как она есть) быть нулевым?

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, сначала может быть выполнен оператор if () в MyTest2, а затем x будет иметь значение ноль .. верно?

или я не думаю прямо.

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

5 голосов
/ 14 августа 2010

Может ли вывод этой программы (так оно и есть) быть нулевым?

Да, это возможно. Код никоим образом не гарантирует, что t1 завершится до окончания t2. Если это ваше намерение, вы можете найти CountdownLatch или CyclicBarrier полезными. Нажмите на ссылки, их Javadocs содержит примеры кода.


Тем не менее, я бы предпочел передать ссылку на AtomicInteger в качестве аргумента конструктора обеих исполняемых таблиц, а не обращаться к нему статическим способом.

1 голос
/ 14 августа 2010

С одним небольшим изменением вы можете гарантировать, что выход будет 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 было опечаткой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...