2015-10-11 9 views
7

Ich habe an Orten gelesen, dass es keine gute Programmierpraxis ist, ein Lock Objekt zu erwerben, ohne dass der folgende Code in einem try...finally Block enthalten ist, so dass das Schloss selbst dann ausgelöst werden kann, wenn eine Ausnahme ausgelöst wird.Löscht ein Thread eine Sperre, wenn es fertig ist?

Es klingt vielleicht wie eine einfache Frage: Werden alle zu einem Thread gehörenden Sperren automatisch freigegeben, wenn der Thread fertig ist?

Der Grund, warum ich diese Frage stelle, ist, dass das Programm, an dem ich arbeite, so ist, dass sobald ein Thread eine Sperre erwirbt, es keinen Grund haben sollte, bis es beendet ist. Außerdem bin ich neu in der Verwendung von Sperren, also frage ich mich, ob es irgendwelche Fallstricke gibt, die ich vielleicht nicht berücksichtigt habe. Muss ich mir Sorgen darüber machen, dass Sperren explizit in meinem Code freigegeben werden, bevor der Thread beendet wird, oder kann ich es der JVM überlassen, da ich sicher bin, dass andere Threads, die auf allen Sperren des aktiven Threads blockiert sind, sofort aktiviert werden Faden stoppt?

+0

Bitte poste etwas Code. – C1sc0

+0

@ C1sc0: Irgendein Code über was? Die Frage hat eine ziemlich klare Problemstellung – Patrick

+0

Sie können dies wahrscheinlich mit einer sehr einfachen Anwendung testen. Erstellen Sie zwei Threads, versuchen Sie, die gleiche Sperre zu erhalten und den Thread direkt danach zu beenden. Wenn der zweite Thread die Sperre erhält, ist er tatsächlich entsperrt. – Patrick

Antwort

3

Einfacher Test können Ihnen diese Sperre zeigt, ist nicht auf Threadbeendigung freigegeben:

import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.LockSupport; 
import java.util.concurrent.locks.ReentrantLock; 

public class LockTest { 
    public static void main(String[] args) { 
     final Lock l = new ReentrantLock(); 

     Thread t = new Thread() { 
      @Override 
      public void run() { 
       System.out.println(Thread.currentThread()+": Acquire lock"); 
       l.lock(); 
       System.out.println(Thread.currentThread()+": Lock aquired: wait"); 
       LockSupport.parkNanos(1_000_000_000); 
       System.out.println(Thread.currentThread()+"; Exiting"); 
      } 
     }; 
     t.start(); 
     LockSupport.parkNanos(500_000_000); 
     System.out.println(Thread.currentThread()+": Acquire lock"); 
     l.lock(); 
     System.out.println(Thread.currentThread()+"; Success!"); 
    } 
} 

Ausgang:

Thread[Thread-0,5,main]: Acquire lock 
Thread[Thread-0,5,main]: Lock aquired: wait 
Thread[main,5,main]: Acquire lock 
Thread[Thread-0,5,main]; Exiting 
// "Success" is never written: stuck in dead-lock 

Also, wenn der separate Thread die Sperre erworben, dann verlassen, Schloss kann nicht genommen werden, nach Hauptthread.

+0

Es wäre nett zu assoziieren Sperren, die von einem bestimmten Thread mit diesem Thread erworben wurden - die API (etwas überraschend) scheint dies nicht zu tun. Ich nehme an, kann eine Sammlung von erworbenen Sperren in einer benutzerdefinierten Thread-Implementierung halten und sie alle freigeben, bevor der Thread beendet werden soll. Ich weiß nicht, ob das Fallstricke hat ... –

+0

@OwenThomas, API verknüpft die Sperre mit Thread. Sie können dies überprüfen, indem Sie versuchen, die erworbene Sperre von einem anderen Thread zu entsperren: Sie erhalten eine Ausnahme. Das Hinzufügen eines automatischen Entsperrens nach dem Ende des Threads ist zu viel unnötiger Arbeit und unnötigem Overhead. –

+0

Gibt es eine Methode, die ich auf den aktuellen Thread aufrufen kann - etwas wie getLocks() - das eine Sammlung zurückgibt, die die Thread-Sperren enthält? –

Verwandte Themen