Das folgende Code für mein Semaphoren-Beispiel (http://openbook.galileodesign.de/javainsel7/javainsel_10_006.htm) habe ich vereinfacht und ist so nicht wirklich korrekt:
1: static Runnable r = new Runnable() {2: public void run() {3: while ( true ) {4: try
5: {6: semaphore.acquire();7:8: System.out.println( "Thread=" + Thread.currentThread().getName() +
9: ", Available Permits=" + semaphore.availablePermits() );
10: Thread.sleep( 2000 );11: }12: catch ( InterruptedException e ) {
13: e.printStackTrace();14: }15: finally {
16: semaphore.release();17: }18: }19: }20: };Wer findet den Fehler noch?
Nun, in der 10. Auflage ist der Fehler jedenfalls korrigiert und ein Dank geht an Marco Völz.
Ähnliche Beiträge
Mir fallen zwei Probleme auf:
Wenn acquire eine InterruptedException wirft und somit die Zahl der permits nicht reduziert wurde, wird sie durch den finally Block mit release trotzdem erhöht.
Außerdem sollte die InterruptedException nicht ignoriert werden. In diesem Fall wäre es sinnvoll die Endlosschleife zu verlassen und dem Interrupt so gerecht zu werden. Ansonsten muss zumindest der Status mit Thread.currentThread().interrupt() zurückgesetzt werden.
Ich versuche es mal:
Wenn der Thread während dem Warten auf den Permit mit Semaphore#aquire() im try-Block unterbrochen wird, fliegt die InterruptedException *und* es wird Semaphore#release() im finally-Block unabhängig davon ausgeführt, ob der Thread nun tatsächlich den Permit erhalten hat oder nicht.
Das führt im Zweifel dazu, dass mehr als die beabsichtigten zwei Threads gleichzeitig laufen können.
Oder um die Dokumentation zu Semaphore#release() zu zitieren:
„There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire(). Correct usage of a semaphore is established by programming convention in the application.“
— http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Semaphore.html#release%28%29
Ich kann das Beispiel in Auflage 9 der Insel gar nicht finden!? Bin ich blind oder wo steckt es?
Das Beispiel gibt in der Auflage 7 und 8, nicht in 9 und kommt wieder in 10. Der Grund ist, dass die Insel immer dicker wurde und ich Dinge entfernen musste. Eine ganze Reihe von Absätzen und auch ganze Kapiteln wurden entfernt und kommen jetzt für die 10. Auflage wieder rein, da die Insel auf zwei Bände verteilt wird. Da habe ich wieder schön viel Platz auch für komplett neue Dinge etwa für JUnit, JavaFX oder Dateiformate.