2012-05-23 5 views
3

멀티 스레딩을 광범위하게 사용하는 응용 프로그램을 작성하고 있습니다. 일부 스레드는 ReaderWriterLockSlim을 사용하여 observablecollection을 공유합니다.누가 ReaderWriterLockSlim을 소유하고 있는지 어떻게 알 수 있습니까?

나는 교착 상태가 발생하면 교착 상태에 빠져있는 스레드인지 알 필요가있다. 어떻게 알 수 있습니까? 나는 물체의 속성을 살펴 봤고 명백한 것은 없었습니다. 현재 알고있는 것은 모든 스레드가 잠금을 기다리고 있다는 것입니다.

도움 주셔서 감사합니다.

편집 : 물론 디버그 시간에 모든 디버그 정보를 사용할 수 있습니다.

답변

3

교착 상태에서 스레드 디버깅 패널의 현재 스레드를 살펴보고 호출 스택을 살펴보면 어떤 스레드가 잠금을 받았는지 확인할 수 있습니다.

코드에서 스레드 ID를 알아야 할 경우 항상 정적으로 저장하거나 readerwriterlockslim에서 상속하고 스레드 속성을 추가 할 수 있습니다.

+0

20에서 30 사이의 스레드가 있습니다. 쓰레드를 가져간 사람은 멀리 떨어진 메서드에서 호출 스택을 보았을 때 충분하지 않았기 때문에 readerwriterlock이 이미 현재 소유자를 나타내는 속성을 가지기를 바랬습니다. –

+0

당신이 말했듯이 자손이라고 나는 생각합니다. –

+0

20 개 또는 30 개의 스레드가 있다면 각 스레드를 돌아 다니는 것보다 지루할 수 있습니다. 그러나 교착 상태에 빠진다고 말하면 모든 스레드가 같은 위치에서 대기하고 하나의 스레드가 "호출"등에서 기다리고있는 것을 볼 수 있습니다. 스레드 패널의 "위치 열"을 빠르게 살펴보십시오. –

2

잠금 전후에 항상 스레드 ID 추적을 시도 할 수 있으므로 어떤 일이 발생했는지, 잠근 사용자 및 기록을 기록 할 수 있습니다. 파일에 쓰거나 디버거 출력 창을 체크하여 모든 트레이스를 볼 수 있습니다. 출력 창에 빠른 무언가를 가지기 위해 실제 추적 코드 대신 추적 중단 점 (중단 점 -> 때 맞음 ...)을 사용할 수 있다고 생각합니다.

2

ReaderWriterLockSlim은 봉인되어 있지 않으므로 서브 클래 싱하여 원하는 방식으로 첨부 할 수 있습니다. 문제는 유용한 메소드가 가상이 아니므로이를 대체 할 수 없다는 것입니다. 그러나 EnterReadLockDebugExitReadLockDebug 등과 같이 메서드가 호출 된 스레드를 캡처하는 것 외에도 EnterReadLockExitReadLock을 백그라운드에서 호출하는 메서드를 추가 할 수 있습니다. 이것은 모든 통화 사이트를 변경해야하기 때문에 훌륭한 솔루션은 아닙니다. 그러나 디버거를 사용하는 것이 너무 번거로운 경우 합당한 대안이 될 수 있습니다.

조건부 컴파일을 사용하는 테마에는 많은 변형이 있습니다. Debug vs. Release 빌드를 감지하고 활성화 된 빌드 구성에 따라 필요한 디버깅 로직을 삽입 할 수 있습니다. Debug가 활성화되어있을 때 디버깅 정보를 주입하고 Release가 활성 상태 일 때 생략합니다.

0

이것은 내가 나중에 참조 할 수 있도록, 함께 종료 코드는 다음과 같습니다

여기
using System; 
using System.Threading; 

namespace Utils 
{ 
public class ReaderWriterLockSlim2 
{ 
    #region Attributes 

    private readonly TimeSpan _maxWait; 
    private readonly ReaderWriterLockSlim _lock; 

    #endregion 

    #region Properties 

    public int CurrentWriteOwnerId { get; private set; } 
    public string CurrentWriteOwnerName { get; private set; } 

    #endregion 

    #region Public Methods 

    public ReaderWriterLockSlim2(LockRecursionPolicy policy, TimeSpan maxWait) 
    { 
     _maxWait = maxWait; 
     _lock = new ReaderWriterLockSlim(policy); 
    } 

    public void EnterWriteLock() 
    { 
     if (!_lock.TryEnterWriteLock(_maxWait)) 
     { 
      throw new TimeoutException(string.Format("Timeout while waiting to enter a WriteLock. Lock adquired by Id {0} - Name {1}", this.CurrentWriteOwnerId, this.CurrentWriteOwnerName)); 
     } 
     else 
     { 
      this.CurrentWriteOwnerId = Thread.CurrentThread.ManagedThreadId; 
      this.CurrentWriteOwnerName = Thread.CurrentThread.Name; 
     } 
    } 

    public void ExitWriteLock() 
    { 
     _lock.ExitWriteLock(); 
     this.CurrentWriteOwnerId = 0; 
     this.CurrentWriteOwnerName = null; 
    } 

    public void EnterReadLock() 
    { 
     _lock.EnterReadLock(); 
    } 

    public void ExitReadLock() 
    { 
     _lock.ExitReadLock(); 
    } 

    #endregion 
} 
} 
2

가 무슨 의미가 있습니다.
잠금 및 잠금 해제를 추적하기 만하면 교착 상태에 도달하면 시스템이 정지하고 마지막 "Enter"키를 누르면 잠금 스레드 방향이 표시됩니다.

public class ReaderWriterLockSlimExtended : ReaderWriterLockSlim 
{ 
    private Thread m_currentOwnerThread = null; 
    private object m_syncRoot = new object(); 

    public Thread CurrentOwnerThread 
    { 
     get 
     { 
      lock (m_syncRoot) 
      { 
       return m_currentOwnerThread; 
      } 
     } 
    } 

    public Thread CurrentOwnerThreadUnsafe 
    { 
     get 
     { 
      return m_currentOwnerThread; 
     } 
    } 

    public new void EnterWriteLock() 
    { 
     lock (m_syncRoot) 
     { 
      base.EnterWriteLock(); 
      m_currentOwnerThread = Thread.CurrentThread; 
     } 
     Debug.WriteLine("Enter Write Lock - Current Thread : {0} ({1})", CurrentOwnerThread.Name, CurrentOwnerThread.ManagedThreadId); 
    } 

    public new void ExitWriteLock() 
    { 
     Debug.WriteLine("Exit Write Lock - Current Thread : {0} ({1})", CurrentOwnerThread.Name, CurrentOwnerThread.ManagedThreadId); 
     lock (m_syncRoot) 
     { 
      m_currentOwnerThread = null; //Must be null before exit! 
      base.ExitWriteLock(); 
     } 
    } 
}