Programing

Java에서 교착 상태 감지

lottogame 2020. 11. 27. 07:38
반응형

Java에서 교착 상태 감지


오래 전에 저는 Java 참고서에서 "Java는 교착 상태를 처리하는 메커니즘이 없습니다. 교착 상태가 발생했는지조차 알지 못합니다." 라는 문장을 저장 했습니다. (Head First Java 2nd Edition, p.516)

그래서, 그것에 대해 무엇입니까? Java에서 교착 상태를 포착하는 방법이 있습니까? 제 말은, 우리 코드가 교착 상태가 발생했음을 이해하는 방법이 있습니까?


JDK 1.5 이후로 java.lang.management발생하는 교착 상태를 찾고 검사 하는 데 매우 유용한 방법이 패키지에 있습니다. 클래스 findMonitorDeadlockedThreads()findDeadlockedThreads()방법을 참조하십시오 ThreadMXBean.

이를 사용하는 가능한 방법은이를 수행하는 별도의 감시 스레드 (또는 주기적 작업)를 갖는 것입니다.

샘플 코드 :

  ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
  long[] ids = tmx.findDeadlockedThreads();
  if (ids != null) {
     ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
     System.out.println("The following threads are deadlocked:");
     for (ThreadInfo ti : infos) {
        System.out.println(ti);
     }
  }

JConsole 은 실행중인 애플리케이션에서 교착 상태를 감지 할 수 있습니다.


JDK 5 및 6은 전체 스레드 덤프 (kill -3, jstack, jconsole 등으로 획득)에 보유 된 잠금 정보를 덤프합니다. JDK 6에는 ReentrantLock 및 ReentrantReadWriteLock에 대한 정보도 포함되어 있습니다. 이 정보에서 잠금주기를 찾아 교착 상태를 진단 할 수 있습니다. 스레드 A는 잠금 1을 보유하고, 스레드 B는 잠금 2를 보유하고, A는 2를 요청하거나 B는 1을 요청합니다. 제 경험상, 이것은 일반적으로 매우 분명합니다.

다른 분석 도구는 실제로 발생하지 않더라도 잠재적 인 교착 상태를 찾을 수 있습니다. OptimizeIt, JProbe, Coverity 등과 같은 공급 업체의 스레드 도구는보기에 좋은 곳입니다.


디버그하기 매우 어려운 동시 패키지를 사용하는 교착 상태 유형이 있습니다. 여기서 ReentrantReadWriteLock이 있고 한 스레드가 읽기 잠금을 잡고 나서 쓰기 잠금을 잡기 위해 대기중인 다른 스레드가 보유한 모니터에 들어 가려고 시도합니다. 특히 디버깅을 어렵게 만드는 것은 누가 읽기 잠금을 입력했는지에 대한 기록이 없다는 것입니다. 단순히 카운트입니다. 스레드는 예외를 throw하고 읽기 횟수를 0이 아닌 상태로 남겨 둘 수도 있습니다.

다음은 앞서 언급 한 findDeadlockedThreads 메서드가 얻을 수없는 샘플 교착 상태입니다.

import java.util.concurrent.locks.*;
import java.lang.management.*;

public class LockTest {

    static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String[] args) throws Exception {
        Reader reader = new Reader();
        Writer writer = new Writer();
        sleep(10);
        System.out.println("finding deadlocked threads");
        ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
        long[] ids = tmx.findDeadlockedThreads();
        if (ids != null) {
            ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
            System.out.println("the following threads are deadlocked:");
            for (ThreadInfo ti : infos) {
                System.out.println(ti);
            }
        }
        System.out.println("finished finding deadlocked threads");
    }

    static void sleep(int seconds) {
        try {
            Thread.currentThread().sleep(seconds*1000);
        } catch (InterruptedException e) {}
    }

    static class Reader implements Runnable {
        Reader() {
            new Thread(this).start();
        }
        public void run() {
            sleep(2);
            System.out.println("reader thread getting lock");
            lock.readLock().lock();
            System.out.println("reader thread got lock");
            synchronized (lock) {
                System.out.println("reader thread inside monitor!");
                lock.readLock().unlock();
            }
        }
    }

    static class Writer implements Runnable {
        Writer() {
            new Thread(this).start();
        }
        public void run() {
            synchronized (lock) {
                sleep(4);
                System.out.println("writer thread getting lock");
                lock.writeLock().lock();
                System.out.println("writer thread got lock!");
            }
        }
    }
}

일반적으로 Java는 교착 상태 감지를 제공하지 않습니다. 동기화 된 키워드와 내장 된 모니터는 명시 적 잠금을 사용하는 언어보다 교착 상태에 대해 추론하기가 다소 어렵습니다.

잠금 체계를 더 쉽게 추론 할 수 있도록 java.util.concurrent.Lock 잠금 등을 사용하여 마이그레이션하는 것이 좋습니다. 실제로 교착 상태 감지 기능을 사용하여 잠금 인터페이스를 쉽게 구현할 수 있습니다. 알고리즘은 기본적으로 잠금 종속성 그래프를 탐색하고주기를 찾는 것입니다.


Java 5를 사용 findMonitorDeadlockedThreads()하는 경우 ThreadMXBean 에서 메서드 를 호출하여 java.lang.management.ManagementFactory.getThreadMXBean(). 이것은 개체 모니터에 의해서만 발생하는 교착 상태를 찾습니다. Java 6에는 findDeadlockedThreads()"소유 가능한 동기화 프로그램 (예 : ReentrandLockReentrantReadWriteLock) "으로 인한 교착 상태도 발견됩니다 .

이러한 메서드를 호출하는 것은 비용이 많이들 수 있으므로 문제 해결 목적으로 만 사용해야합니다.


모든 스레드가 동일한 순서로 잠금을 요청하고 해제하도록하는 간단한 규칙을 따르면 교착 상태를 피할 수 있습니다. 이렇게하면 교착 상태가 발생할 수있는 상황에 빠지지 않습니다.

식사 철학자 문제조차도 왼쪽과 오른쪽 스푼의 상대적인 개념을 사용하여 스푼의 다른 할당 순서를 사용하여 다른 스레드를 생성하므로이 규칙을 위반 한 것으로 볼 수 있습니다. 숟가락에 고유 한 번호가 매겨져 있고 철학자들이 모두 가장 낮은 번호의 숟가락을 먼저 얻으려고하면 교착 상태가 불가능합니다.

제 생각에는 예방이 치료보다 낫습니다.

이것은 스레드가 제대로 작동하는지 확인하기 위해 따르는 두 가지 지침 중 하나입니다. 다른 하나는 각 스레드가 특정 시점에서 수행하는 작업을 완전히 인식하는 유일한 스레드이므로 자체 실행에 대해 전적으로 책임을지는 것입니다.

즉, Thread.stop호출이 없음을 의미 하며 전역 플래그 (또는 메시지 대기열 또는 이와 유사한 것)를 사용하여 작업을 수행하려는 다른 스레드에 알립니다. 그런 다음 해당 스레드가 실제 작업을 수행하도록합니다.


정확히 요청한 것은 아니지만 교착 상태 발생하면 프로세스 ID에 대해 "kill -3"을 수행 할 수 있으며 stdout에 스레드 덤프를 덤프합니다. 또한 1.6 jvm에는 GUI 방식으로 동일한 작업을 수행하는 몇 가지 도구가 있습니다.


If you are running from the command-line and you suspect that you are deadlocked, try ctrl+break in windows (ctrl+\ in unix) to get a thread dump. See http://java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/gbmps.html


Dr. Heinz Kabutz of JavaSpecialists has written an entertaining and informative newsletter issue on Java deadlocks and describes something called a ThreadMXBean in another newsletter issue. Between those, you should get a good idea of the issues and some pointers to doing your own instrumentation.


Java can detect deadlocks (although not at run-time, it can still diagnose and report it).

For example, when using a slightly modified version of 'Saurabh M. Chande' code bellow (changed it to Java and added some timing to guarantee a lock on each run). Once you run it and it deadlocks, if you type:

kill -3 PID   # where 'PID' is the Linux process ID

It will generate a stack dump, which will include the following information:

Found one Java-level deadlock:
=============================
"Thread-0":
     waiting to lock monitor 0x08081670 (object 0x7f61ddb8, a Deadlock$A),
     which is held by "main"
"main":
      waiting to lock monitor 0x080809f0 (object 0x7f61f3b0, a Deadlock$B),
      which is held by "Thread-0"

If you're debugging in eclipse, you can pause the application (select the app in the debug view and the little || button on the debug toolbar) and then it can report deadlocks.

See http://runnerwhocodes.blogspot.com/2007/10/deadlock-detection-with-eclipse.html for an example.


Java 5 introduced ThreadMXBean - an interface that provides various monitoring methods for threads. ... The difference is that findDeadlockedThreads can also detect deadlocks caused by owner locks (java.util.concurrent), while findMonitorDeadlockedThreads can only detect monitor locks (i.e. synchronized blocks)

Or you can detect it programatically, refer this https://dzone.com/articles/how-detect-java-deadlocks


After so long, i am able to write the simplest example of Deadlock. Comments are welcome.

Class A
{
  synchronized void methodA(B b)
  {
    b.last();
  }

  synchronized void last()
  {
    SOP(“ Inside A.last()”);
  }
}

Class B
{
  synchronized void methodB(A a)
  {
    a.last();
  }

  synchronized void last()
  {
    SOP(“ Inside B.last()”);
  }
}


Class Deadlock implements Runnable 
{
  A a = new A(); 
  B b = new B();

  // Constructor
  Deadlock()
  {
    Thread t = new Thread(); 
    t.start();
    a.methodA(b);
  }

  public void run()
  {
    b.methodB(a);
  }

  public static void main(String args[] )
  {
    new Deadlock();
  }
}

you have to modify the code a little bit in the Deadlock Class

   Deadlock() {
    Therad t = new Thread(this); // modified
    t.start();
    System.out.println(); //any instruction to delay
    a.methodA(b);
}

Also the above code will not always cause a dead lock, only some times it may happen.

참고URL : https://stackoverflow.com/questions/217113/deadlock-detection-in-java

반응형