Domanda

È possibile in fase di esecuzione controllare a livello di codice il nome del thread che detiene il blocco di un determinato oggetto?

È stato utile?

Soluzione

Puoi solo dire se il thread corrente ha un blocco normale (Thread.holdsLock(Object)).Non è possibile ottenere un riferimento al thread che ha il blocco senza codice nativo.

Tuttavia, se stai facendo qualcosa di complicato con il threading, probabilmente vorrai familiarizzare con i pacchetti java.util.concurrent.IL ReentrantLock ti consente di ottenere il suo proprietario (ma è un metodo protetto, quindi dovresti estenderlo).A seconda dell'applicazione, è possibile che utilizzando i pacchetti di concorrenza si scoprirà che, dopo tutto, non è necessario conoscere il proprietario del blocco.

Esistono metodi non programmatici per trovare i proprietari del blocco, come segnalare alla JVM di inviare un dump del thread a stderr, utili per determinare la causa dei deadlock.

Altri suggerimenti

Puoi arrivare alle serrature trattenute da fili con riflessione.Funziona solo con Java 1.6.

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] ti = bean.getThreadInfo(bean.getAllThreadIds(), true, true);

Su ciascuno di questi oggetti ThreadInfo sono presenti oggetti LockInfo su cui è possibile utilizzare l'identityHashCode per confrontare il blocco in questione.

Dalla versione 1.6 puoi usare JMX per fare ogni sorta di cose interessanti, inclusa la ricerca di serrature bloccate.Non puoi ottenere l'oggetto reale, ma ottieni il valore hash della classe e dell'identità (che non è univoco).

C'è un esempio in uno dei miei blog.

Correre jconsole.È incluso in Java SDK e viene eseguito dalla riga di comando.Non sono sicuro di quale sistema operativo stai utilizzando, ma su Windows puoi semplicemente passargli il PID del processo Java.Dovrebbe aiutarti a trovare il thread che causa il problema.Oppure puoi utilizzare un profiler commerciale come YourKit o un numero qualsiasi di altri profiler.

Nella versione 1.5 puoi trovare tutti i thread e ottenere lo stato di ciascuno, ad esempio in questo modo:

    Map<Thread,StackTraceElement[]> map = Thread.getAllStackTraces();
    for (Map.Entry<Thread, StackTraceElement[]> threadEntry : map.entrySet()) {
        log.info("Thread:"+threadEntry.getKey().getName()+":"+threadEntry.getKey().getState());
        for (StackTraceElement element : threadEntry.getValue()) {
            log.info("--> "+element);
        }
    }

Thread.getState ti fornisce informazioni sul fatto che il thread sia BLOCCATO, IN ATTESA ecc., vedi jdk API ThreadState

È possibile verificare il blocco su un particolare oggetto chiamando wait() O notify() metodo su quell'oggetto.Se l'oggetto non mantiene il lucchetto, verrà lanciato llegalMonitorStateException .

2- Chiamando holdsLock(Object o) metodo.Ciò restituirà il valore booleano.

se è serratura rientrante puoi controllare se è mantenuto dal thread corrente

final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();

Puoi utilizzare una variabile per contenere il thread corrente quando prendi il blocco, quindi stamparlo se qualcun altro sta tentando di usarlo.

Thread holderOfLock = null;
Object theLock = new Object();

public void doStuff()
{
    if(holderOfLock != null)
    {
       //get and print name of holderOfLock-thread or get stacktrace etc.
    }

    synchronized (theLock)
    {
        holderOfLock = Thread.currentThread();
        //do stuff...
        holderOfLock = null;
    }
}

Brutto ma funziona.

String findLockOwner(ReentrantLock lock) {
    String patternStr = "\\[Locked by thread (\\S+)\\]";
    Pattern pattern = Pattern.compile(patternStr);
    Matcher matcher = pattern.matcher(lock.toString());
    boolean matchFound = matcher.find();
    if (matchFound && matcher.groupCount() >= 1) {
      return matcher.group(1);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top