2016-02-28 2 views
1

Я пытаюсь изучить концепцию взаимодействия потоков в java и выработал следующий код. Я заметил, что когда я запускаю код с System.out.println("from t1: " + c1.value()); и System.out.println("from t2: " + c1.value());, распечатанным результатом будет всегда равен 20000.результат приращения переменной int изменяется из-за наличия или отсутствия операторов System.out.println()

Однако, когда я запускаю код без System.out.println() заявления, результат всегда будет 10000 < < результата 20000 . Почему это происходит?

public class Counter { 

    public static void main(String[] args) throws InterruptedException { 
     Counter c1 = new Counter(); 
     Thread t1 = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       for (int i = 0; i < 10000; i++) { 
        c1.increment(); 
        System.out.println("from t1: " + c1.value()); 
       } 
      } 

     }); 

     Thread t2 = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       for (int i = 0; i < 10000; i++) { 
        c1.increment(); 
        System.out.println("from t2: " + c1.value()); 
       } 
      } 

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

     System.out.println(c1.value()); 
    } 

    private int c = 0; 

    public void increment() { 
     c++; 
    } 

    public void decrement() { 
     c--; 
    } 

    public int value() { 
     return c; 
    } 
} 
+1

В прошлом я заметил, что добавление оператора System.out.print в код может значительно замедлить код, если он находится в цикле/рекурсии. Поэтому я предполагаю, что, поскольку оператор печати замедляет выполнение, оба потока имеют время для выполнения всех приращений без вмешательства, и без println() не все регистры увеличиваются, поэтому вы получаете меньше 20000. Не уверен хоть. – Maljam

ответ

1

Операторы печати замедляют потоки, достаточные для того, чтобы помехи были проблемой. Когда операторы печати удаляются, ваши потоки могут пройти через все итерации 10E4 до того, как они будут отменены. Таким образом, время, затрачиваемое на поток для повторения 10E4 раз, слишком короткое. Если вы считаете, что 10E5 вместо 10E4, вы, вероятно, увидите помехи даже в отсутствие операторов печати.

Чтобы проиллюстрировать, дайте p оператором печати и дайте + быть приращением. Обозначим начальную нить событие, S и прекращения с T С заявлениями печати у вас есть что-то вроде:

t1:  S| +p+p+p+... | idle | +p+pT | 
t2:   S| idle |+p+p+p+... | idle | +pT| 
main:   |    idle    | p 

Без заявлений печати у вас есть что-то вроде:

t1: S| ++++++ T| 
t2:     S| ++++++ T| 
main:     | idle | p 

Примечание: На моей машине, я могу перебирать всего 5000 и видеть помехи.

+1

Большое спасибо за подробное объяснение! теперь все начинает иметь смысл. :) – Thor

Смежные вопросы