3

編集:私がすでに得た答えから、私が提示した最初の解決策は、実際には「読み取りをブロックしない」ではないことを理解しています。これは、読み取りが解放される前に1つのスレッドのみがアップグレード可能なロックに入ることができ、書き込みロックを取得できないためです...

だから私の質問、存在しない場合は作成で「読み取りをブロックしない」という最初の解決策を正しい方法で作成するにはどうすればよいですか?


マルチスレッド読み取りをブロックしないための2つの解決策を理解しようとしています。以下の2つのソリューションの違いは何ですか(まだいくつかのことを理解していないかもしれませんが、試しています):

/// <summary>
/// ReaderWriterLockSlim pattern
/// </summary>
public class ReadWriteLockCheck
{
    Dictionary<string, object> _dict = new Dictionary<string, object>();

    private ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);

    public void CreateByKey(string key)
    {
        _rwLock.EnterReadLock();
        try
        {
            if (!_dict.ContainsKey(key)) //Non blocking read - Check if exists
            {
                _rwLock.EnterWriteLock(); //Lock
                try
                {
                    _dict.Add(key, new object());
                }
                finally
                {
                    _rwLock.ExitWriteLock();
                }
            }
        }
        finally
        {
            _rwLock.ExitReadLock();
        }
    }

    public bool GetByKey(string key)
    {
        _rwLock.EnterWriteLock();
        try
        {
            if (_dict.ContainsKey(key)) //Non blocking read
            {
                return true;
            }

            return false;
        }
        finally
        {
            _rwLock.ExitReadLock();
        }
    }
}

/// <summary>
/// Double check lock pattern
/// </summary>
public class MonitorLock
{
    Dictionary<string, object> _dict = new Dictionary<string, object>();

    private object _syncObj = new Object();

    public void CreateByKey(string key)
    {
        if (!_dict.ContainsKey(key)) //Non blocking read - Check if exists
        {
            Monitor.Enter(_syncObj); //Lock
            try
            {
                if (!_dict.ContainsKey(key)) //Check if between first check and lock someone already added
                {
                    _dict.Add(key, new object());
                }
            }
            finally
            {
                Monitor.Exit(_syncObj);
            }
        }
    }

    public bool GetByKey(string key)
    {
        if (_dict.ContainsKey(key)) //Non blocking read
        {
            return true;
        }

        return false;
    }
}

私の場合、これらのソリューションはどちらも、非ブロッキング読み取りを実行し、書き込み時にのみブロッキングを実行できます...もしそうなら、どのような利点がありReaderWriterLockSlimますか?私がグーグルで見つけたように、Monitorはよりはるかに速いですReaderWriterLockSlim。もちろん、読んでいるときに辞書の状態が間違ってしまう可能性があることは理解していますが、私にとっては問題ありません。
ありがとう

4

1 に答える 1

5

MSDN から:

一度に 1 つのスレッドのみがアップグレード可能モードに入ることができます

基本的に、完全なロックを使用するよりもはるかに優れているとは言えません-lock実際にはより高速であったことを除いて.

奇妙なことに、ここでの 1 つの良いアプローチは次のとおりですHashtable。特に、値がobjectであり、キーが参照型であるため (余分なボックス化はありません)。読み取りが完全にスレッドセーフHashtableであるという点で異常です。複数のライターから保護する必要があるだけです。

例えば:

readonly Hashtable lookup = new Hashtable();

...

object val = lookup[key]; // no need to synchronize when reading

...

lock(lookup)
{
    lookup[key] = newVal; // synchronize when writing
}
于 2013-01-08T13:05:00.933 に答える