Давайте посмотрим на этот код:
Import java.util.bitset; Поток t1 = new Thread (new Runnable () {public void run () {try {latch.await (); thread.sleep (1000);} catch (Exception ex) {} bs.set (1);}); Поток t2 = new Thread (new Runnable () {public void run () {try {latch.await (); thread.sleep (1000);} catch (Exception e) {} bs.set (2);}}) ; start (); :}}Вопрос в том, что является результатом этого вывода кода? Какие результаты он может вывести?
Давайте посмотрим на то, что делает эта программа:
Затем нам нужно построить некоторые тестовые случаи, чтобы проверить это поведение. Очевидно, что один из них может запустить только этот пример, а затем наблюдать за результатами и ответить на вопросы выше.
Осторожность может сделать совпадение
К счастью, мы можем использовать инструменты. JCStress - это тестовый инструмент для решения таких проблем.
Мы можем легко написать наш тестовый пример как форму, которую JCStress может распознать. На самом деле, он подготовил для нас множество интерфейсов. Нам нужен пример.
Мы используем интерфейс actor2_arbiter1_teest <bitset, booleanresult2>. Нам нужно найти Java 8 JVM, чтобы запустить его, но теперь это не проблема.
Посмотрите на реализацию ниже.
Общедоступный класс anexampletest реализует actor2_arbiter1_test <bitset, booleanresult2> {@override public void actor1 (bitset s, booleanresult2 r) {s.set (1);} @override public void actor2 (bitset s, booleanresult2 r) );} @Override public void arbiter1 (bitset s, booleanresult2 r) {r.r1 = s.get (1); ;} @Override public boolenrSult2 newresult () {return new booleanresult2 ();}}
Теперь при проведении этого теста управление будет пробовать все виды трюков, чтобы получить все возможные комбинации факторов, которые управляют этими действиями: параллельными или невозможными, не существует обнаружения нагрузки, и в одной линии много раз много раз, много раз, Много раз, много раз, много раз, поэтому все возможные результаты будут записаны.
Когда вы хотите знать, как находится ваш параллельный код, это лучший способ выкопать пустую мысль и подумать обо всех деталях, чем о себе.
Кроме того, чтобы использовать всеобъемлющее удобство, принесенное ограничениями JCStress, мы должны предоставить его объяснение возможных результатов.
<test name = "org.openjdk.jcstress.tests.custom.anexampletest"> <appened-by> oleg shelajev </open-by> <Описание, если бицет работает хорошо с синхронизацией > Match> [true, true] </match> <weard> приемлемо </wearm> <description> Видеть все обновления нетронутыми. /Ожидайте> <SOMNAD> T2 перезаписывает результат T1 >
Теперь мы готовы к тому, чтобы этот зверь начал рев.
java -xx:+unlockdiagnosticvmoptions -xx:+whiteboxapi -xx: -resterictconded -jar tests -custot/target/jcstress.jar -t = ".*anexampletest"
Результат, который мы получаем, является элегантным отчетом.
Понятно, что мы можем не только получить ожидаемые результаты, то есть оба потока установили свои позиции, но также сталкиваются с конкурентным условием, и один поток будет охватывать результат другого потока.
Даже если вы видите такую вещь, у вас должен быть спокойный менталитет «у горных людей есть свои уловки», не так ли?
Кстати, если вы думаете о том, как изменить этот код, ответ состоит в том, чтобы тщательно прочитать класс Bitset в Javadoc и понять, что это не безопасность потока и требует внешней синхронизации. Это может быть легко достигнуто путем увеличения значений настройки синхронных блоков.
синхронизированный (bs) {bs.set (1);}