• 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 可能会引入新的公平策略。

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

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

  • 相关阅读:
    数据类型
    一些骚操作
    re
    多任务
    监听按钮点击事件
    监听按钮点击事件
    监听按钮点击事件
    将博客搬至博客园
    将博客搬至博客园
    将博客搬至博客园
  • 原文地址:https://www.cnblogs.com/Tpf386/p/12190877.html
Copyright © 2020-2023  润新知