Мне нужно написать модульный тест, который вызывает состояние гонки, чтобы я мог проверить, исправил ли я проблему позже. Проблема в том, что условие гонки встречается очень редко, может быть, потому что у моего компьютера всего два ядра.
Код выглядит примерно так:
class MyDateTime {
String getColonTime() {
// datetime is some kind of lazy caching variable declared somewhere(does not matter)
if (datetime == null) {
initDateTime(); //Uses lazy to initlialize variable, takes some time
}
// Colon time stores hh:mm as string
if (datetime.colonTime == null) {
StringBuilder sb = new StringBuilder();
//Now do some steps to build the hh:mm string
//...
//set colon time
datetime.colonTime = sb.toString();
}
return datetime.colonTime;
}
}
Объяснение: initDateTime назначает новый экземпляр dateTime, поэтому datetime.colonTime после этого имеет значение null (поскольку мы хотим инициализировать его лениво, как я уже говорил ранее ). Теперь, если поток A входит в метод, а затем планировщик останавливает его непосредственно перед тем, как он сможет запустить initDateTime (). Поток B теперь запускает getColonTime (), видит, что datetime все еще имеет значение null, и инициализирует его. datetime.colonTime имеет значение null, поэтому второй блок if выполняется, а datetime.colonTime получает значение StringBuilder. Если тогда планировщик останавливает поток между этой строкой и оператором return и возобновляет поток A, происходит следующее : Поскольку A был остановлен непосредственно перед вызовом initDateTime, A теперь вызывает initDateTime (), который как бы сбрасывает объект datetime, снова устанавливая для datetime.colonTime значение null. Затем поток A войдет во второй блок if, но планировщик прервет A до того, как datetime.colonTime = sb.toString (); называется. В заключение, dateTime.colonTime все еще имеет значение null. Теперь планировщик возобновляет B, и метод возвращает значение null.
Я пытался спровоцировать состояние гонки, имея несколько потоков, вызывающих getColonTime () для единственного (последнего) экземпляра MyDateTime, но это терпит неудачу только в очень редких случаях: ( Любые подсказки, как написать "тест" JUnit?