Muszę napisać test jednostkowy, który wywołuje stan wyścigu, aby przetestować, czy prawdopodobnie rozwiązałem problem później. Problem polega na tym, że stan wyścigu występuje bardzo rzadko, może dlatego, że mój komputer ma tylko dwa rdzenie.Wywołanie warunków wyścigu w Javie
Kod jest coś takiego, co następuje:
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;
}
}
Objaśnienie: initDateTime przypisuje nową instancję do DateTime nich, datetime.colonTime jest null potem (jak chcemy zainicjować to leniwe, jak stwierdziłem przed). Teraz, jeśli wątek A wprowadza metodę, a następnie program planujący zatrzymuje ją tuż przed uruchomieniem metody initDateTime(). Wątek B teraz runst getColonTime(), widzi, że data/godzina jest nadal pusta i inicjuje ją. datetime.colonTime ma wartość null, więc drugi blok if jest wykonywany, a datetime.colonTime pobiera wartość StringBuilder. Jeśli następnie program planujący zatrzyma wątek między tą linią a instrukcją return i wznowi wątek A, następuje: Ponieważ A zostało zatrzymane tuż przed wywołaniem initDateTime, A wywołuje teraz initDateTime(), która będzie w pewnym sensie zresetować obiekt datetime, ustawiając datetime.colonTime ponownie na wartość null. Wątek A następnie wchodzi do drugiego bloku if, ale program planujący przerwie A przed datetime.colonTime = sb.toString(); jest nazywany. Podsumowując, dateTime.colonTime jest wciąż zerowy. Teraz program planujący wznawia B, a metoda zwraca wartość null.
Próbowałem sprowokować warunki wyścigu, mając wiele wątków wywołujących getColonTime() do pojedynczej (końcowej) instancji MyDateTime, ale zawodzi tylko w niektórych wyjątkowo rzadkich przypadkach :( Wszelkie wskazówki, jak napisać JUnit "test"?
Możesz spróbować najpierw użyć debuggera, aby sprowokować stan wyścigu. To znaczy. uruchom wątek, złap go w punkcie przerwania (np. między jeśli jest) i uruchom inny - i tak dalej. Po uzyskaniu idei, w jaki sposób RC się dzieje (wydaje się, że nie masz tego teraz) możesz napisać udany test jednostkowy – pupssman
Nie widzę, jak można dostać się do 'daty powrotu.colonTime; 'i odzyskaj null. Czy jesteś pewien, że nie ma problemu z budowaniem ciągu hh: mm? Może dodaj ten kod do swojego pytania, abyśmy mogli na to spojrzeć. – Windle
Dodałem kilka dodatkowych wyjaśnień, dlaczego tak się stało. Muszę przyznać, że nie jest to zbyt oczywiste. – user3001