2016-08-26 6 views
3

Рассмотрим следующий многопоточный код, написанный на Java:JMM В практике

Общие переменные:

  boolean n; // non-volatile 
volatile boolean v; //  volatile 

темы 1:

v = true; 
System.out.println("n=" + n); 

Тема 2:

n = true; 
System.out.println("v=" + v); 

Предположим, изначально n = v = false.

Сейчас:

  • выход v=false Означает ли выход n=true?
  • Что изменилось бы, если бы n были неустойчивыми?
  • Что бы изменилось, если n были java.util.List (так что n = true становится n.add("something") и выход n=true превращается в ["something"])?
  • UPD3: Что делать, если v были AtomicBoolean и все считывание и пишет к нему осуществляется с compareAndSet семантическим?

Не могли бы вы утверждать свое положение в соответствии с моделью памяти Java?

UPD: Просьба обработать System.out.println("n=" + n) как раз от n. То же самое для v.

UPD2: Не могли бы вы дать некоторый анализ 1-го и 4-го корпусов, как показано в JSR-133 сек. 8?

ответ

0

Там действительно три способа, код может выполнять:

// Thread 1 runs first 
T1: v = true; 
T1: System.out.println("n=" + n); // prints n=false 

// Thread 2 runs second 
T2: n = true; 
T2: System.out.println("v=" + v); // prints v=true 
// They run in parallel, so assignments first, in any order 
T1: v = true; 
T2: n = true; 

// Print statements second, in any order 
T1: System.out.println("n=" + n); // may print n=true or n=false (depends on CPU caching) 
            // will print n=true if n is volatile 
T2: System.out.println("v=" + v); // prints v=true 
// Thread 2 runs first 
T2: n = true; 
T2: System.out.println("v=" + v); // prints v=false 

// Thread 1 runs second 
T1: v = true; 
T1: System.out.println("n=" + n); // may print n=true or n=false (depends on CPU caching) 
            // will print n=true if n is volatile 

выход V = ложный Подразумевает ли выход п = верно?

№ Как вы можете видеть в третьем сценарии, n может печатать либо значение.

Что изменится, если n будет изменчивым?

Как прокомментировал n напечатает true в сценарии 2 и 3, вместо того, чтобы быть неопределенными.

Что изменилось бы, если n было java.util.List (так что n = true становится n.add ("something"), а выход n = true преобразуется в ["something"])?

Это предполагает, что n уже List, прежде чем сценарии запуска, поэтому волатильность n не имеет значения.

Будет ли печать n увидеть вставленное значение в зависимости от типа списка. Если список не является параллельным, ответ будет таким же, как и для вопроса 1: он может увидеть или не увидеть новое значение.Примеры неконкурирующих списков:

Если список параллельный, он будет увидеть новое значение. Примеры параллельных списков:

+2

Проблема с такого рода анализов что они полностью игнорируют разрешенные переупорядочивания. Да, в мире последовательной согласованности это было бы правильно, но вы не можете получить это в Java - по крайней мере, не с изменчивым. Вы * можете * переупорядочивать волатильные чтения перед изменчивой записью, не нарушая JMM, и вдруг появляется еще несколько возможных путей, которые вы игнорировали. – Voo

+0

@ Voo, это именно то, что я хочу видеть. Детальный анализ ситуации по JSR-133 сек. 8. Обновлен исходный вопрос. (Извините, что первоначально упомянул Андреаса, моя небрежность) – kalaider

+1

@ Kalaider JSR длинный и невероятно формальный. Даже неофициальный анализ займет много времени - больше, чем я готов потратить. Легко сказать, что если вы используете не синхронизированный список, вы не можете писать в гонках с чем-то еще, поэтому по этой причине он будет сломан. – Voo

1

У вас здесь есть два фактора.

  • у вас есть volatile поле, но
  • у вас есть synchronized вызов System.out.println Это действует для чтения/записи барьер

В обоих потоков вы выполняете запись и чтение. Барьер записи не гарантирует считывания барьера.

Имеет ли выход v = false вывод n = true?

Если вы видите v=false вы можете увидеть n=false и наоборот

Что изменится, если п были неустойчивыми?

Не совсем, вы можете увидеть изменение в поведении в зависимости от архитектуры, на которой вы работаете, однако вы все еще можете видеть неопределенное поведение некоторых машин.

Что бы изменить, если п были java.util.List

Основное изменение замене барьера записи например n = true с барьером считывания n.method Это означает, что у вас больше нет барьера для записи (кроме вызова синхронного метода)

Это означает, что существует множество причин, по которым согласованность между потоками прерывается.

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