Devo scrivere un test unitario che provoca una condizione di gara, così posso verificare se ho probabilmente risolto il problema in seguito. Il problema è che la condizione di gara si verifica solo molto raramente, forse perché il mio computer ha solo due core.Provocazione di una condizione di competizione in Java
Il codice è simile al seguente:
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;
}
}
Spiegazione: initDateTime assegna una nuova istanza per dateTime, Perciò, datetime.colonTime è nullo in seguito (come vogliamo inizializzare pigro, come ho detto prima). Ora se il thread A entra nel metodo e quindi lo scheduler lo arresta poco prima che possa essere avviato initDateTime(). Thread B ora runstColonTime(), vede che datetime è ancora null e lo inizializza. datetime.colonTime è null, quindi il secondo blocco if viene eseguito e datetime.colonTime ottiene il valore di StringBuilder. Se quindi lo scheduler interrompe il thread tra questa riga e l'istruzione return e riprende il thread A, accade quanto segue: Poiché A è stato arrestato appena prima di initDateTime viene chiamato, A chiama ora initDateTime(), che sarà il reset oggetto datetime, impostazione di datetime.colonTime su null. Il thread A quindi entrerà nel secondo se blocco, ma lo scheduler interromperà A prima di datetime.colonTime = sb.toString(); è chiamato. In conclusione, dateTime.colonTime è ancora nullo. Ora lo scheduler riprende B e il metodo restituisce null.
Ho provato a provocare la condizione di competizione avendo un numero di fili di chiamata getColonTime() per una singola istanza (finale) di MyDateTime, ma non riesce solo in alcuni casi rari extreeemly :( Eventuali suggerimenti come scrivere un JUnit "test"?
Si potrebbe provare prima ad utilizzare il debugger per provocare condizioni di competizione. Cioè avvia un thread, prendilo su un punto di interruzione (come tra if) e avvialo un altro - e così via. Dopo aver avuto l'idea di come accade RC (sembra che tu non abbia nulla del genere ora) potresti scrivere un test unitario di successo – pupssman
Non vedo come potresti arrivare al 'return datetime.colonTime; 'e restituisce null. Sei sicuro che non sia un problema con il modo in cui stai costruendo la stringa hh: mm? Forse aggiungi quel codice alla tua domanda in modo che possiamo guardarlo. – Windle
Ho aggiunto qualche spiegazione in più sul perché possa accadere. Devo ammettere che non è molto ovvio – user3001