Net Concurrency locks

object _lock

The concept of locks, where not elaborate. Start with the most classic application scenarios, the singleton without considering the static constructor to achieve, to achieve a lock is a must. such as:

public class Singleton
{
    private static Singleton _Singleton = null;
    private static object Singleton_Lock = new object();
    public static Singleton CreateInstance()
    {
        if (_Singleton == null)  
        {
            lock (Singleton_Lock)
            { 
                if (_Singleton == null)
                { 
                    _Singleton = new Singleton();
                }
            }
        }
        return _Singleton;
    }
}

Here we note

static object Singleton_Lock = new object()

Lock here, in fact, it is a syntactic sugar, a specific definition is not to say, is not the focus of this article. Briefly about precautions lock of
1. lock object must be a reference type (string type rather special, is CLR 'persistence', it does not work)
2. lock is recommended to use a static, private, read-only object.
3. For 2 read-only, is the need to ensure that can not be modified outside the lock. Also added that the reasons for the string type does not work the first point.
4. lock (this), if you can not guarantee whether the other threads and external access, it is best not so. Because a deadlock may occur.

To sum up, lock (readonly static referenceTypes) is the most elegant way to use.

Net3.5 in ReaderWriterLockSlim

ReaderWriterLockSlim supports three locking mode
1. the Read
2. the Write
3. UpgradeableRead
method of three corresponding locking mode are:
1. EnterReadLock
2. EnterWriteLock
3. EnterUpgradeableReadLock

Which, Read mode is a shared lock mode, any thread can simultaneously obtain a lock in this mode.
Write mode are mutually exclusive mode, any number of threads allows only one thread to enter the lock.

In fact, this blog's purpose is to test the performance of traditional Object_lock and the difference ReaderWriteLockSlim. Ado, using Zhao brother of the realization CodeTimer

Test code is as follows:

public class MemoryCache<TKey, TValue>
{
    private ConcurrentDictionary<TKey, TValue> _dicCache = new ConcurrentDictionary<TKey, TValue>();

    private Dictionary<TKey, Lazy<TValue>> _dicLazyValue = new Dictionary<TKey, Lazy<TValue>>();

    private ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim();

    private object _locker = new object();

    public TValue GetValueByObjectLocker(TKey key, Lazy<TValue> value)
    {
        if (!_dicLazyValue.ContainsKey(key))
        {
            lock (_locker)
            {
                if (!_dicLazyValue.ContainsKey(key))
                {
                    _dicLazyValue.Add(key, value);
                }
            }
        }
        if (_dicCache == null)
        {
            lock (_locker)
            {
                if (_dicCache == null)
                {
                    _dicCache = new ConcurrentDictionary<TKey, TValue>();
                }
            }
        }
        return _dicCache.GetOrAdd(key, _dicLazyValue[key].Value);
    }


    public TValue GetValueByLockSlim(TKey key, Lazy<TValue> value)
    {
        if (!_dicLazyValue.ContainsKey(key))
        {
            try
            {
                _cacheLock.EnterWriteLock();
                if (!_dicLazyValue.ContainsKey(key))
                {
                    _dicLazyValue.Add(key, value);
                }
            }
            finally
            {
                _cacheLock.ExitWriteLock();
            }
        }
        if (_dicCache == null)
        {
            try
            {
                _cacheLock.EnterUpgradeableReadLock();
                if (_dicCache == null)
                {
                    _dicCache = new ConcurrentDictionary<TKey, TValue>();
                }
            }
            finally
            {
                _cacheLock.ExitUpgradeableReadLock();
            }
        }
        return _dicCache.GetOrAdd(key, _dicLazyValue[key].Value);
    }
}

Using a console application

static void Main(string[] args)
{
    MemoryCache<string, string> _memoryCache = new MemoryCache<string, string>();
    CodeTimer.Initialize();
    CodeTimer.Time("object lock", 1000, () =>
    {
        var lazyStr = new Lazy<string>(() => Thread.CurrentThread.ManagedThreadId.ToString());
        _memoryCache.GetValueByObjectLocker("123", lazyStr);
    });

    CodeTimer.Time("LockSlim", 1000, () =>
    {
        var lazyStr = new Lazy<string>(() => Thread.CurrentThread.ManagedThreadId.ToString());
        _memoryCache.GetValueByLockSlim("456", lazyStr);
    });
    System.Console.WriteLine("123");
    System.Console.ReadLine();
}

result:

object lock
    Time Elapsed:   7ms
    CPU Cycles:     6,414,332
    Gen 0:          0
    Gen 1:          0
    Gen 2:          0

LockSlim
    Time Elapsed:   1ms
    CPU Cycles:     3,182,178
    Gen 0:          0
    Gen 1:          0
    Gen 2:          0

In summary, there is used when the next 'lock' when requested priority ReaderWriterLockSlim for higher performance and lower CPU Cycles.

Guess you like

Origin www.cnblogs.com/YamatAmain/p/11589256.html