Hier ist mein Ansatz. Dieser Test befasst sich nicht mit Deadlocks, sondern mit der Konsistenz. Ich teste eine Methode mit einem synchronisierten Block, mit Code, der etwa wie folgt aussieht:
synchronized(this) {
int size = myList.size();
// do something that needs "size" to be correct,
// but which will change the size at the end.
...
}
Es ist schwierig, ein Szenario zu erzeugen, die zuverlässig einen Thread Konflikt produzieren, aber hier ist, was ich tat.
Zuerst erstellt mein Komponententest 50 Threads, startete sie alle zur gleichen Zeit und ließ sie alle meine Methode aufrufen. Ich benutze einen CountDown Latch sie alle zur gleichen Zeit zu starten:
CountDownLatch latch = new CountDownLatch(1);
for (int i=0; i<50; ++i) {
Runnable runner = new Runnable() {
latch.await(); // actually, surround this with try/catch InterruptedException
testMethod();
}
new Thread(runner, "Test Thread " +ii).start(); // I always name my threads.
}
// all threads are now waiting on the latch.
latch.countDown(); // release the latch
// all threads are now running the test method at the same time.
Dies kann oder kann nicht einen Konflikt erzeugen. Meine testMethod() sollte eine Ausnahme auslösen können, wenn ein Konflikt auftritt. Aber wir können noch nicht sicher sein, dass dies zu einem Konflikt führen wird. Wir wissen also nicht, ob der Test gültig ist. Also hier ist der Trick: Kommentieren Sie Ihre synchronisierten Schlüsselwort (e) und führen Sie den Test aus. Wenn dies zu einem Konflikt führt, wird der Test fehlschlagen. Wenn es ohne das synchronisierte Schlüsselwort fehlschlägt, ist Ihr Test gültig.
Das habe ich gemacht, und mein Test ist nicht ausgefallen, also war es (noch) kein gültiger Test. Aber ich war in der Lage, einen Fehler zuverlässig zu produzieren, indem ich den obigen Code in eine Schleife setzte und ihn 100 Mal hintereinander ablaufen ließ. Also rufe ich die Methode 5000 mal an. (Ja, das erzeugt einen langsamen Test. Mach dir keine Sorgen. Deine Kunden werden davon nicht gestört, also solltest du auch nicht.)
Sobald ich diesen Code in eine äußere Schleife, I war in der Lage, einen Fehler bei der 20. Iteration der äußeren Schleife zuverlässig zu erkennen.Jetzt war ich zuversichtlich, dass der Test gültig war, und ich stellte die synchronisierten Schlüsselwörter wieder her, um den eigentlichen Test auszuführen. (Es hat funktioniert.)
Möglicherweise stellen Sie fest, dass der Test auf einer Maschine und nicht auf einer anderen Maschine gültig ist. Wenn der Test auf einem Computer gültig ist und Ihre Methoden den Test bestehen, ist er vermutlich Thread-sicher auf allen Computern. Sie sollten jedoch auf der Maschine, auf der Ihre nächtlichen Komponententests ausgeführt werden, auf Gültigkeit prüfen.
Ich habe Komponententests in der Weise durchgeführt, die Sie zuvor beschrieben haben, aber immer das Gefühl, dass es ein Element der Zufälligkeit im Ergebnis gibt, also werde ich die Antworten hier mit Interesse verfolgen: o) –
Duplizieren: http: // stackoverflow.com/questions/1715822/unit-test-for-thread-safe-ness – JeffH
@JeffH Ja, du hast das richtig gemacht. Pffffff, hör auf zu versuchen, ein Polizist zu sein. –