2017-02-14 45 views
2

Вот код:Почему код о потоке показывает a = 1 и b = 3? и почему добавить «изменчивость» не получилось?

public class ThreadCacheSample { 
    int a = 1; 
    int b = 2; 

    public void change() { 
     a = 3; 
     b = a; 
    } 

    public void print() { 
     if (a == 1 && b == 3) { 
      // why this is happening? 
      System.out.println("Thread[" + Thread.currentThread().getName() + "]Confused1 : a = 1, b = 3"); 
     } else if (a == 3 && b == 2) { 
      // why this is happening, too? 
      System.out.println("Thread[" + Thread.currentThread().getName() + "]Confused2 : a = 3, b = 2"); 
     } else { 
      System.out.println("Thread[" + Thread.currentThread().getName() + "] b=" + b + ";a=" + a); 
     } 
    } 

    public static void main(String[] args) { 
     // create many many threads 
     while (true) { 
      // create test every time, to make sure a is 1 and b is 2 again 
      final ThreadCacheSample test = new ThreadCacheSample(); 

      // one thread for changing 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        try { 
         Thread.sleep(10); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
        test.change(); 
       } 
      }).start(); 

      // one thread for printing 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        try { 
         Thread.sleep(10); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
        test.print(); 
       } 
      }).start(); 

     } 
    } 
}  

Результат должен быть = 1, B = 2, или = 3, б = 3.

Мои вопросы:

  1. Почему бы мне получить результат, который показывает «a = 1, b = 3» или «a = 3, b = 2»?

  2. Если я добавлю «volatile» в a и b, почему это не сработало? Я думал, что volatile сделает каждый поток доступным только к основной памяти, а не к собственной рабочей памяти. Поэтому неустойчивым должно быть решение. Но реальность говорит мне, что «изменчивость» также не является решением.

    public class ThreadCacheSample { 
        volatile int a = 1; 
        volatile int b = 2; 
        ... 
    } 
    

P.S. Это не вопрос о том, как исправить код. Речь идет о том, почему появляется странный результат?

+1

Ваши заявления о печати неверны. Они не представляют условие в 'if'.Кроме того, сначала вы можете сначала записать их значения в локальных переменных, а затем работать только с локальными переменными. –

+0

Простите, что вы подразумеваете под словом «Ваши заявления о печати неверны. Они не представляют условие в if»? – songzhw

+1

Оба они печатают '] Confused1: a = 1, b = 3'. –

ответ

5

Добавление изменчивой увеличивает индивидуальность видимых изменений a и b (а также добавляет зависимость между видимостью их модификаций). он делает не, однако добавьте любые виды «атомарности» к их объединенным модификации. «летучих» или нет, модификация a и модификация b (а также показания a и показания b) по-прежнему независимых действия!

Оба ваших "спутать" ответы возможны:

Случай 1:

  1. первонач A == 1, б == 2
  2. печати нить испытания "а == 1"
  3. изменение резьбы устанавливает "а = 3"
  4. изменение резьбы устанавливает "A = B" (3)
  5. печати нить испытания "б == 3"
  6. confused1

Случай 2:

  1. первонач, A == 1, б == 2
  2. изменение резьбы устанавливает "а = 3"
  3. печать испытаний нить «а == 3"
  4. печати нить испытания "б == 2"
  5. confused2

Обратите внимание, что без volatile, вы можете получить даже более удачные ответы, такие как поток печати, видящий «a == 1, b == 3»!

+0

Существует ли вообще «volatile» вообще? Как он кодируется, оба потока имеют доступ к тем же самым переменным. Если что-то может работать медленнее из-за 'write-through' при каждой модификации. –

+0

@JanezKuhar - я не уверен, что вы подразумеваете под «доступом к переменным», но волатильность исключает одну возможность, как я упомянул в своем последнем предложении. и, конечно же, волатильность оказывает влияние на производительность. – jtahlborn

+0

Вы правы, он не может напечатать a = 1, b = 3, если используется 'volatile', мой плохой. –