在C#中,如何知道线程是否在等待为ReaderWriterLockSlim输入写锁定?

时间:2015-11-25 20:48:52

标签: c# multithreading list parallel-processing thread-safety

我正在尝试为列表实现ReaderWriterLockSlim。我希望每个线程能够立即从列表中读取,但只允许一个线程允许"等待"用于写锁定。如果一个线程试图在另一个线程已经写入或等待写入时试图控制写锁定,我希望它不要等待锁定。我找到了TryEnterReadLock(Int32)方法,但根据我的理解,它只会等到调用线程可以控制写锁定或达到超时。我会尝试使用" 0"的超时,但是,我不认为这会工作,因为如果其他线程拥有读锁定,它将在获得对写锁定的访问之前超时。我知道我可以使用变量来表示线程是在写还是在等待写,但我想知道是否有更专业的方法来做这个(我不想创建另一个变量)因此必须为它创建一个互斥锁。)

1 个答案:

答案 0 :(得分:0)

进一步向前移动逻辑,在读取器上使用TryEnterUpgradeableReadLock,超时0,然后一个读者成为你的作者,等待其他读者完成。

public void YourFunction()
{
    bool enteredUpgLock = false;
    bool enteredWriteLock = false;

    try
    {
        //Preemptively take a upgradeable read lock, only one thread can do this.
        enteredUpgLock = _readerWriterLock.TryEnterUpgradeableReadLock(0);

        try
        {
            //If we don't have the upgradeable lock take a normal read lock.
            if (!enteredUpgLock)
            {
                _readerWriterLock.EnterReadLock();
            }

            DoReadWork();
        }
        finally
        {
            //Release the read lock if we had it.
            if(!enteredUpgLock)
                _readerWriterLock.ExitReadLock();
        }

        try
        {
            if (enteredUpgLock)
            {
                //We held the upgradeable lock, wait forever till we can take it.
                _readerWriterLock.EnterWriteLock();
                enteredWriteLock = true;
            }
            else
            {
                //We did not have the upgrade lock, try to take the write lock but if we can't bail out.
                enteredWriteLock = _readerWriterLock.TryEnterWriteLock(0);
                if(!enteredWriteLock)
                    return;
            }

            DoWriteWork();
        }
        finally 
        {
            if(enteredWriteLock)
                _readerWriterLock.ExitWriteLock();
        }
    }
    finally 
    {
        //If we had the upgradeable lock, release it.
        if (enteredUpgLock)
        {
            _readerWriterLock.ExitUpgradeableReadLock();
        }
    }
}