AIX® occupato si blocca

Se non vi è alcun deadlock tra i thread, considerare altri motivi per cui i thread non stanno eseguendo un lavoro utile.

Generalmente, questo stato si verifica per uno dei seguenti motivi:
  1. I thread sono in uno stato di 'attesa 'in attesa di essere' informati ' del lavoro da eseguire.
  2. I thread sono in cicli di sospensione espliciti.
  3. I thread sono in chiamate I/O in attesa di eseguire il lavoro.
I primi due motivi implicano un errore nel codice Java™ , quello dell'applicazione o quello dei file di classe standard inclusi nell'SDK.

Il terzo motivo, dove i thread sono in attesa (ad esempio, sui socket) di I/O, richiede un'ulteriore analisi. Il processo all'altra estremità dell'I/O ha avuto esito negativo? Esistono problemi di rete?

Per informazioni su come viene utilizzato lo strumento javadump per diagnosticare i loop, consultare THREADS. Se non è possibile diagnosticare il problema dal javadump e se il processo sembra ancora utilizzare i cicli del processore, è stato immesso un loop infinito o le prestazioni sono molto cattive. Utilizzando ps -mp [process id] -o THREAD è possibile monitorare i singoli thread in un particolare processo per determinare quali thread stanno utilizzando il tempo della CPU. Se il processo è entrato in un loop infinito, è probabile che un piccolo numero di thread utilizzerà l'ora. Ad esempio:

$ ps -mp 43824 -o THREAD
    USER   PID  PPID     TID ST  CP PRI SC    WCHAN        F     TT BND COMMAND
  wsuser 43824 51762       - A   66  60 77        *   200001  pts/4   - java ...
       -     -     -    4021 S    0  60  1 22c4d670   c00400      -   - -
       -     -     -   11343 S    0  60  1 e6002cbc  8400400      -   - -
       -     -     -   14289 S    0  60  1 22c4d670   c00400      -   - -
       -     -     -   14379 S    0  60  1 22c4d670   c00400      -   - -
...
       -     -     -   43187 S    0  60  1 701e6114   400400      -   - -
       -     -     -   43939 R   33  76  1 20039c88   c00000      -   - -
       -     -     -   50275 S    0  60  1 22c4d670   c00400      -   - -
       -     -     -   52477 S    0  60  1 e600ccbc  8400400      -   - -
...
       -     -     -   98911 S    0  60  1 7023d46c   400400      -   - -
       -     -     -   99345 R   33  76  0        -   400000      -   - -
       -     -     -   99877 S    0  60  1 22c4d670   c00400      -   - -
       -     -     -  100661 S    0  60  1 22c4d670   c00400      -   - -
       -     -     -  102599 S    0  60  1 22c4d670   c00400      -   - -
...

I thread con il valore 'R' in 'ST' si trovano nello stato 'eseguibile' e, quindi, sono in grado di accumulare tempo del processore. Cosa stanno facendo questi fili? L'output da ps mostra il TID (Kernel Thread ID) per ogni thread. Può essere associato all'ID thread Java utilizzando dbx. L'output del comando dbx thread fornisce un output nel formato:

thread  state-k     wchan    state-u    k-tid   mode held scope function
 $t1     wait      0xe60196bc blocked   104099     k   no   sys  _pthread_ksleep
>$t2     run                  blocked    68851     k   no   sys  _pthread_ksleep
 $t3     wait      0x2015a458 running    29871     k   no   sys  pthread_mutex_lock
...
 $t50    wait                 running    86077     k   no   sys  getLinkRegister
 $t51    run                  running    43939     u   no   sys  reverseHandle     
 $t52    wait                 running    56273     k   no   sys  getLinkRegister
 $t53    wait                 running    37797     k   no   sys  getLinkRegister
 $t60    wait                 running     4021     k   no   sys  getLinkRegister
 $t61    wait                 running    18791     k   no   sys  getLinkRegister
 $t62    wait                 running    99345     k   no   sys  getLinkRegister   
 $t63    wait                 running    20995     k   no   sys  getLinkRegister

Facendo corrispondere il valore TID da ps al valore k-tid dal comando thread dbx, si può vedere che i metodi attualmente in esecuzione in questo caso sono reverseHandle e getLinkRegister.

Ora è possibile utilizzare dbx per creare lo stack di thread C per questi due thread utilizzando il comando dbx thread per i corrispondenti numeri di thread dbx ($tx). Per ottenere la traccia di stack completa, inclusi i frame Java, associare il numero del thread dbx al valore pthread_t dei thread, che è elencato dal file Javadump e può essere ottenuto dalla struttura ExecEnv per ogni thread utilizzando il Visualizzatore dump. Eseguire questa azione con il comando dbx thread info [dbx thread number], che produce un output del formato:

thread  state-k     wchan    state-u    k-tid   mode held scope function
 $t51    run                  running    43939     u   no   sys  reverseHandle
      general:
         pthread addr = 0x220c2dc0         size         = 0x18c
         vp addr      = 0x22109f94         size         = 0x284
         thread errno = 61
         start pc     = 0xf04b4e64
         joinable     = yes
         pthread_t    = 3233
      scheduler:
         kernel       =
         user         = 1 (other)
      event :
         event        = 0x0
         cancel       = enabled, deferred, not pending
      stack storage:
         base         = 0x220c8018         size         = 0x40000
         limit        = 0x22108018
         sp           = 0x22106930

Viene mostrato che il valore TID da ps (k - tid in dbx) corrisponde al thread dbx numero 51, che ha un pthread_t di 3233. Ricercando pthread_t nel file Javadump, ora si dispone di una traccia di stack completa:

"Worker#31" (TID:0x36288b10, sys_thread_t:0x220c2db8) Native Thread State: 
ThreadID: 00003233 Reuse: 1 USER SUSPENDED Native Stack Data : base: 22107f80 
pointer 22106390 used(7152) free(250896) 
----- Monitors held -----
java.io.OutputStreamWriter@3636a930 
com.ibm.servlet.engine.webapp.BufferedWriter@3636be78 
com.ibm.servlet.engine.webapp.WebAppRequestDispatcher@3636c270 
com.ibm.servlet.engine.srt.SRTOutputStream@36941820 
com.ibm.servlet.engine.oselistener.nativeEntry.NativeServerConnection@36d84490 JNI pinning lock 

----- Native stack ----- 

_spin_lock_global_common pthread_mutex_lock - blocked on Heap Lock 
sysMonitorEnterQuicker sysMonitorEnter unpin_object unpinObj 
jni_ReleaseScalarArrayElements jni_ReleaseByteArrayElements 
Java_com_ibm_servlet_engine_oselistener_nativeEntry_NativeServerConnection_nativeWrite 

------ Java stack ------ () prio=5 

com.ibm.servlet.engine.oselistener.nativeEntry.NativeServerConnection.write(Compiled Code) 
com.ibm.servlet.engine.srp.SRPConnection.write(Compiled Code) 
com.ibm.servlet.engine.srt.SRTOutputStream.write(Compiled Code) 
java.io.OutputStreamWriter.flushBuffer(Compiled Code) 
java.io.OutputStreamWriter.flush(Compiled Code) 
java.io.PrintWriter.flush(Compiled Code) 
com.ibm.servlet.engine.webapp.BufferedWriter.flushChars(Compiled Code) 
com.ibm.servlet.engine.webapp.BufferedWriter.write(Compiled Code) 
java.io.Writer.write(Compiled Code) 
java.io.PrintWriter.write(Compiled Code) 
java.io.PrintWriter.write(Compiled Code) 
java.io.PrintWriter.print(Compiled Code) 
java.io.PrintWriter.println(Compiled Code)
pagecompile._identifycustomer_xjsp.service(Compiled Code) 
javax.servlet.http.HttpServlet.service(Compiled Code) 
com.ibm.servlet.jsp.http.pagecompile.JSPState.service(Compiled Code) 
com.ibm.servlet.jsp.http.pagecompile.PageCompileServlet.doService(Compiled Code) 
com.ibm.servlet.jsp.http.pagecompile.PageCompileServlet.doGet(Compiled Code) 
javax.servlet.http.HttpServlet.service(Compiled Code) 
javax.servlet.http.HttpServlet.service(Compiled Code)

E, utilizzando la traccia di stack completa, dovrebbe essere possibile identificare qualsiasi loop infinito che potrebbe verificarsi. L'esempio precedente mostra l'utilizzo di spin_lock_global_common, che è un'attesa occupata su un blocco, quindi l'utilizzo del tempo CPU.