如何知道谁拥有ReaderWriterLockSlim?

时间:2012-05-23 20:21:29

标签: c# .net multithreading deadlock readerwriterlockslim

我正在编写一个广泛使用多线程的应用程序。一些线程使用ReaderWriterLockSlim共享一个observablecollection。

我不时遇到死锁,我需要知道哪一个是在死锁时刻持有锁的线程。我怎么知道这个?我看过对象属性,没有什么明显的。目前我所知道的是哪些线程正在等待锁定。

感谢您的帮助!

编辑:我当然是在讨论在调试时找到它并提供所有可用的调试信息。

5 个答案:

答案 0 :(得分:3)

在你的死锁期间,只需查看线程调试面板中的当前线程,查看你的调用堆栈,你就会发现哪个线程已经锁定了。

如果您需要知道代码中的线程ID,您可以始终静态保存它,或者从readerwriterlockslim继承并添加线程属性。

答案 1 :(得分:2)

您总是可以尝试在锁定之前和之后跟踪线程ID,因此您已经记录了发生的事情以及锁定它的时间和时间。您可以写入文件或只是检查调试器输出窗口以查看所有跟踪。 我相信你可以使用跟踪断点(Breakpoint - > When Hit ...)而不是真实的跟踪代码来在输出窗口中快速输入内容。

答案 2 :(得分:2)

ReaderWriterLockSlim未密封,因此您可以将其子类化并附加您需要的任何信息。问题是有用的方法不是虚拟的,所以你不能覆盖它们。但是,除了捕获方法所在的线程之外,您还可以添加自己的方法,如EnterReadLockDebugExitReadLockDebug等在幕后调用EnterReadLockExitReadLock的方法。调用。这不是一个很好的解决方案,因为您必须更改所有呼叫站点。但是,如果使用调试器太麻烦,那么这可能是一个合理的选择。

使用条件编译主题有很多变化。您可以检测Debug与Release版本,并根据活动的构建配置注入必要的调试逻辑。在Debug处于活动状态时注入调试信息,并在Release处于活动状态时省略它。

答案 3 :(得分: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();
        }
    }  
}

答案 4 :(得分: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
}
}