2012-10-10 2 views
0

멀티 스레드 프로그래밍의 개념을 이해하려고합니다. 교착 상태 및 뮤텍스의 개념을 알고 있지만 다음 질문에 대한 답을 찾을 수 없습니다. 뮤텍스가 사용될 때 교착 상태가 발생할 수있는 방법은 무엇입니까?Java에서 mutexes 관련 문제

+0

죄송 합니다만 귀하의 연구 비서가 아닙니다. 게시물을 수정하여 수행 한 조사를 표시하십시오. 어떤 코드를 시도 했습니까? – Gray

+0

교착 상태에 대한 Wikipedia 항목을 살펴보십시오. http://en.wikipedia.org/wiki/Deadlock – Zarkonnen

답변

5

다음은 Java에서 deadlock을 발생시키는 구체적인 예입니다. 우리는 두 개의 스레드를 생성합니다. 첫 번째는 a에서 뮤텍스 잠금을 획득 한 다음 잠시 기다린 다음 b에서 잠금을 획득하려고 시도합니다. 두 번째는 b의 잠금을 획득 한 다음 대기하여 a을 획득하려고 시도합니다. 결과는 프로그램이 교착 상태에 들어가 영원히 실행됩니다.

public class Deadlock { 
    public static void main(String[] args) { 
     final Object a = new Object(); 
     final Object b = new Object(); 
     new Thread() { 
      @Override 
      public void run() { 
       synchronized (a) { 
        /* wait for a second to make it likely the other thread can acquire b */ 
        try { Thread.sleep(1000); } catch (Exception e) { } 
        synchronized (b) { 
         System.out.println("Acquired a, then b."); 
        } 
       } 
      } 
     }.start(); 
     new Thread() { 
      @Override 
      public void run() { 
       synchronized (b) { 
        /* wait for a second to make it likely the other thread can acquire a */ 
        try { Thread.sleep(1000); } catch (Exception e) { } 
        synchronized (a) { 
         System.out.println("Acquired b, then a."); 
        } 
       } 
      } 
     }.start(); 
    } 
} 

참고 교착 상태를 입력을 보장 할 수 없습니다 이 코드가된다. 스레드 스케줄러는 두 번째 스레드 인 또는 그 반대로에서 시작하기 전에 첫 번째 스레드를 완료 할 수있는 권한 내에서 완벽하게 수행 할 수 있습니다. 이 예에서 방대한 대기 시간으로 인해 시스템이 교착 상태에 빠지게 될 것이 확실하지만 1 초 동안 잠자는 대신 두 스레드가 각 잠금 획득 전에 가변 길이의 계산을 수행 중이면 다음 중 하나 무작위로 일어날 수 :이 FR을 방지하려면 어떻게 "Acquired a, then b."

다음 "Acquired b, then a."

  • "Acquired b, then a." 다음

    • 교착 상태
    • "Acquired a, then b.", 무슨 일이야?

      • 벗어날 수있을 때마다 스레드를 사용하지 마십시오.
      • 스레드간에 공유 리소스가있는 대신 각 스레드가 자체 데이터에서 작동하고 서로 다른 불변 메시지를 보냅니다.
      • 절대적으로 공유 리소스를 사용해야하는 경우 사용되는 뮤텍스 잠금 수를 최소화하십시오. 모든 것이 동일한 객체에서 동기화되면 뮤텍스 잠금이 하나만 존재하며 교착 상태가 발생할 수 없습니다.
      • 절대적으로 많은 뮤텍스 잠금이 있어야하며 스레드가 이들의 조합을 획득 한 상태에서 다음을 수행하십시오. 잠금의 전체 순서를 정의하는 함수를 작성하십시오. 그런 다음 여러 뮤텍스가 포함 된 작업을 수행해야 할 때마다 관련된 뮤텍스 목록을 만들어 정렬 한 다음 작업 시작시 정렬 된 순서대로 바로 입력하십시오.

      java.util.concurrent 패키지를 살펴보십시오. 정말 많은 털이 많은 것들을 돌보는 많은 좋은 것들을 포함하고 있습니다.

      또한 예기치 않은 곳에서 스레드가 전환 될 수있는 정도를 과장 할 수 없습니다.일반적인 실수는 각 스레드를 라인 단위로 살펴보고 라인이 인터리브 할 수있는 여러 가지 방법을 상상해 보는 것입니다. 하지만 충분하지 않습니다. 일부 라이브러리 내에서 일부 중첩 된 함수 호출 중간에 스레드가 전환 될 수 있습니다.

  • 0

    죽은 잠금은 한 스레드가 리소스 A를 잠그고 두 번째 스레드가 리소스 B를 잠그는 것을 기다리는 상황입니다. 동시에 두 번째 스레드는 두 번째 스레드가 리소스 B를 잠그고있는 첫 번째 스레드에 의해 잠긴 리소스 A를 기다리고 있습니다. :)

    해결 방법은 "스마트 스레딩 모델 설계 또는 대기열을 사용하는 스레드의 분리 또는 동기화가 필요하지 않은 불변 객체 사용 등

    +0

    유감스럽게도 유권자의 이유는 무엇인지 흥미 롭습니다. – AlexR

    +1

    나는 여기에 보상금이 있습니다. 당신을 위해 upvote. – Zarkonnen

    -1

    동기화 블록의 핵심은 뮤텍스입니다. 동기화 된 블록/mutex 변수의 부적절한 사용으로 인해 dead lock이 발생합니다.

    +0

    downvote에 대한 이유를 알고 싶어 :) –

    0

    잠금 순서 교착 상태를 피하기 위해 다중 잠금을 확보해야하는 경우 Lock 오브젝트를 사용하십시오. 이 경우, Lock 객체 내의 tryLock() 메소드는 즉시 값 false를 반환 할 것이다. 결과적으로 단일 스레드 만 두 잠금을 동시에 보유하게됩니다. 동기화 된 코드의 경우 스레드는 다음 잠금을 기다리는 동안 하나의 객체에 대한 잠금 유지를 차단합니다. 아래 예제 코드를 참조하십시오.

    while (true) { 
        if (a.lock.tryLock()) { 
         try { 
          if (b.lock.tryLock()) { 
           try { 
            // manipulate protected state 
           } finally { 
            b.lock.unlock(); 
           } 
          } 
         } finally { 
          a.lock.unlock(); 
         } 
        } 
    }