zoukankan      html  css  js  c++  java
  • ReaderWriterLockSlim 类

    地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.readerwriterlockslim?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev16.query%3FappId%3DDev16IDEF1%26l%3DZH-CN%26k%3Dk(System.Threading.ReaderWriterLockSlim);k(DevLang-csharp)%26rd%3Dtrue&view=netframework-4.8

    标题:ReaderWriterLockSlim 类

    文章内容摘抄自微软文档。

    表示用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。

    下面的示例演示了一个简单的同步缓存,该缓存包含包含整数键的字符串。 ReaderWriterLockSlim 的实例用于同步对充当内部缓存的 Dictionary<TKey,TValue> 的访问。

    该示例包括要添加到缓存中、从缓存中删除以及从缓存中读取的简单方法。 为了演示超时,此示例包含一个方法,该方法仅在指定的超时时间内添加到缓存中。

    为了演示可升级模式,该示例包含一个方法,该方法检索与键关联的值,并将其与新值进行比较。 如果值不变,则方法将返回一个状态,指示没有任何更改。 如果未找到键的值,则插入键/值对。 如果值已更改,则会更新。 可升级模式允许线程从读取访问权限升级到按需写入访问权限,而不会导致死锁风险。

    该示例包含一个嵌套枚举,该枚举指定演示可升级模式的方法的返回值。

    该示例使用无参数构造函数创建锁,因此不允许使用递归。 当锁定不允许递归时,对 ReaderWriterLockSlim 进行编程更简单,并且不易出错。

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    public class SynchronizedCache 
    {
        private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
        private Dictionary<int, string> innerCache = new Dictionary<int, string>();
    
        public int Count
        { get { return innerCache.Count; } }
    
        public string Read(int key)
        {
            cacheLock.EnterReadLock();
            try
            {
                return innerCache[key];
            }
            finally
            {
                cacheLock.ExitReadLock();
            }
        }
    
        public void Add(int key, string value)
        {
            cacheLock.EnterWriteLock();
            try
            {
                innerCache.Add(key, value);
            }
            finally
            {
                cacheLock.ExitWriteLock();
            }
        }
    
        public bool AddWithTimeout(int key, string value, int timeout)
        {
            if (cacheLock.TryEnterWriteLock(timeout))
            {
                try
                {
                    innerCache.Add(key, value);
                }
                finally
                {
                    cacheLock.ExitWriteLock();
                }
                return true;
            }
            else
            {
                return false;
            }
        }
    
        public AddOrUpdateStatus AddOrUpdate(int key, string value)
        {
            cacheLock.EnterUpgradeableReadLock();
            try
            {
                string result = null;
                if (innerCache.TryGetValue(key, out result))
                {
                    if (result == value)
                    {
                        return AddOrUpdateStatus.Unchanged;
                    }
                    else
                    {
                        cacheLock.EnterWriteLock();
                        try
                        {
                            innerCache[key] = value;
                        }
                        finally
                        {
                            cacheLock.ExitWriteLock();
                        }
                        return AddOrUpdateStatus.Updated;
                    }
                }
                else
                {
                    cacheLock.EnterWriteLock();
                    try
                    {
                        innerCache.Add(key, value);
                    }
                    finally
                    {
                        cacheLock.ExitWriteLock();
                    }
                    return AddOrUpdateStatus.Added;
                }
            }
            finally
            {
                cacheLock.ExitUpgradeableReadLock();
            }
        }
    
        public void Delete(int key)
        {
            cacheLock.EnterWriteLock();
            try
            {
                innerCache.Remove(key);
            }
            finally
            {
                cacheLock.ExitWriteLock();
            }
        }
    
        public enum AddOrUpdateStatus
        {
            Added,
            Updated,
            Unchanged
        };
    
        ~SynchronizedCache()
        {
           if (cacheLock != null) cacheLock.Dispose();
        }
    }

    注解

    使用 ReaderWriterLockSlim 保护由多个线程读取的资源并一次写入一个线程。 ReaderWriterLockSlim 允许多个线程处于读取模式,则允许一个线程处于具有独占锁定所有权的写入模式,并且允许具有读取访问权限的一个线程处于可升级读取模式,在该模式下,线程可以升级到写入模式,而无需放弃对资源的读取访问权限。

     备注

    虽然 ReaderWriterLockSlim 类似于 ReaderWriterLock,但不同之处在于,前者简化了递归规则以及锁状态的升级和降级规则。 ReaderWriterLockSlim 避免了许多潜在的死锁情况。 另外,ReaderWriterLockSlim 的性能显著优于 ReaderWriterLock。 建议对所有新开发的项目使用 ReaderWriterLockSlim

    默认情况下,ReaderWriterLockSlim 的新实例是使用 LockRecursionPolicy.NoRecursion 标志创建的,不允许使用递归。 建议对所有新的开发使用此默认策略,因为递归引入了不必要的复杂性,并使代码更容易发生死锁。 若要简化从使用 Monitor 或 ReaderWriterLock的现有项目的迁移,可以使用 LockRecursionPolicy.SupportsRecursion 标志创建允许递归的 ReaderWriterLockSlim 实例。

    线程可以在三种模式下进入锁定:读取模式、写入模式和可升级读取模式。 (在本主题的其余部分中,"可升级的读取模式" 称为 "可升级模式",将优先使用 "输入 x 模式" 短语来 "在 x 模式下进入锁定"。)

    不管递归策略如何,在任何时候都只能有一个线程处于写入模式。 当线程处于写入模式时,任何其他线程都不能在任何模式下进入锁定状态。 在任何时候,只能有一个线程处于可升级模式。 任意数量的线程都可以处于读取模式,并且在其他线程处于读取模式时,可以有一个处于可升级模式的线程。

     重要

    此类型实现 IDisposable 接口。 在使用完类型后,您应直接或间接释放类型。 若要直接释放类型,请在 Disposetry/ 块中调用其 catch 方法。 若要间接释放类型,请使用 using(在 C# 中)或 Using(在 Visual Basic 中)等语言构造。 有关详细信息,请参阅 IDisposable 接口主题中的“使用实现 IDisposable 的对象”一节。

    ReaderWriterLockSlim 具有托管线程关联;也就是说,每个 Thread 对象都必须进行自己的方法调用来进入和退出锁模式。 任何线程都无法更改另一个线程的模式。

    如果 ReaderWriterLockSlim 不允许使用递归,尝试进入锁定的线程可能会出于多种原因而阻塞:

    • 如果有等待进入写入模式的线程或在写入模式下有单个线程,则尝试进入读取模式的线程会被阻止。

       备注

      在编写器排队时阻止新的读取器是优先写入器的锁公平策略。 当前的公平策略在最常见的情况下,将公平与读者和编写者进行平衡,以提高吞吐量。 未来版本的 .NET Framework 可能会引入新的公平策略。

    • 如果已存在处于可升级模式的线程,则为尝试进入可升级模式的线程,如果存在等待进入写入模式的线程,则为; 如果在写入模式下有单个线程,则为。

    • 如果在三种模式中的任何一种模式下有线程,则尝试进入写入模式块的线程。

  • 相关阅读:
    第二十一章流 1流的操作 简单
    第二十章友元类与嵌套类 1友元类 简单
    第十九章 19 利用私有继承来实现代码重用 简单
    第二十章友元类与嵌套类 2嵌套类 简单
    第十九章 8链表类Node 简单
    第二十一章流 3用cin输入 简单
    第十九章 10 图书 药品管理系统 简单
    第十九章 11图书 药品管理系统 简单
    第二十一章流 4文件的输入和输出 简单
    第十九章 12 什么时候使用私有继承,什么时候使用包含 简单
  • 原文地址:https://www.cnblogs.com/Tpf386/p/12190877.html
Copyright © 2011-2022 走看看