• C# 读写锁 ReaderWriteLock


        ReaderWriterLock 用於同步存取資源。

        它能在任何指定時間並行讀取多重執行緒或寫入單一執行緒。 如果資源不常變更,ReaderWriterLock 的產量優於每次一的鎖定 (例如 Monitor)。

        如果不常寫入 (而且寫入時間很短) 而是以讀取為主,則 ReaderWriterLock 最適合。 多重讀取器和單一寫入器交替,就不會長期鎖定讀取器和寫入器。

        長期保留讀取器鎖定或寫入器鎖定,會影響其他執行緒。 為獲得最佳效能,您不妨考慮重組應用程式將寫入期間縮至最小。

        執行緒可以保留讀取器鎖定或寫入器鎖定,但不能同時執行。

        與其釋放讀取器鎖定取得寫入器鎖定,您不妨使用 UpgradeToWriterLockDowngradeFromWriterLock

       遞迴鎖定要求會增加鎖定上的鎖定計數。

    讀取器和寫入器是個別佇列。 執行緒釋放寫入器鎖定時,在讀取器佇列中等候的所有執行緒都會獲得讀取器鎖定;釋放所有讀取器鎖定時,在寫入器佇列中等候的下一個執行緒 (若有) 會獲得寫入器鎖定,以此類推。 換言之,ReaderWriterLock 在讀取器集合和寫入器集合之間交替。

    寫入器佇列中的執行緒正在等候釋放讀取器鎖定時,要求新讀取器鎖定的執行緒也不斷在讀取器佇列中累積。 即使這些要求可以和現有讀取器鎖定的持有人共用並行存取,卻仍然不會同意這些要求;此一措施可以協助避免讀取器持續鎖定寫入器的情況。

    大部分取得鎖定 ReaderWriterLock 的方法會接受逾時值。 逾時可用來避免應用程式鎖死。 例如,執行緒可能在一個資源上取得寫入器鎖定,並在第二個資源上取得讀取器鎖定;同時可能有另一個執行緒在第二個資源上取得寫入器鎖定,並在第一個資源上取得讀取器鎖定。 此時除非使用逾時,否則執行緒會鎖死。

    如果逾時間隔到期但鎖定要求並未獲准,這個方法會擲回 ApplicationException,將控制項傳回至呼叫執行緒。 執行緒可以攔截這個例外狀況,並決定下一個採取動作。

    逾時值是以毫秒為單位。 如果您使用 System.TimeSpan 指定逾時,則會使用 TimeSpan 表示的毫秒總整數。 下表顯示有效的逾時值 (以毫秒為單位)。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;

    namespace ConsoleApplication1
    {
    class Program
    {
    //读线程锁
    static ReaderWriterLock m_ReadLock =new ReaderWriterLock();
    static ReaderWriterLock m_WriteLock =new ReaderWriterLock();
    //资源
    staticint m_nResource =0;

    //读取资源线程
    staticvoid ReadProc()
    {
    for (int i =0; i <5; i++)
    {
    ReadResource(
    5000);
    Thread.Sleep(
    500);
    }
    }

    //写入资源线程
    staticvoid WriteProc()
    {
    for (int i =0; i <5; i++)
    {
    WriteResource(
    5000);
    Thread.Sleep(
    500);
    }
    }

    //读取资源
    privatestaticbool ReadResource(int timeout)
    {
    try
    {
    m_ReadLock.AcquireReaderLock(timeout);
    try
    {
    Console.WriteLine(
    "成功获得读线程锁, 资源值:{0}", m_nResource);
    }
    finally
    {
    m_ReadLock.ReleaseReaderLock();
    }
    }
    catch (ApplicationException ex)
    {
    Console.WriteLine(
    "获取锁超时:{0}", ex.Message);
    }
    catch (Exception ex)
    {
    Console.WriteLine(
    "获取锁异常:{0}", ex.Message);
    }
    returntrue;
    }

    //写入资源
    privatestaticbool WriteResource(int timeout)
    {
    try
    {
    m_WriteLock.AcquireWriterLock(timeout);
    try
    {
    Console.WriteLine(
    "成功获得写线程锁, 资源值:{0}", m_nResource);
    m_nResource
    ++;
    Console.WriteLine(
    "写入资源 {0}", m_nResource);
    }
    finally
    {
    m_WriteLock.ReleaseWriterLock();
    }
    }
    catch (ApplicationException ex)
    {
    Console.WriteLine(
    "获取锁超时:{0}", ex.Message);
    }
    catch (Exception ex)
    {
    Console.WriteLine(
    "获取锁异常:{0}", ex.Message);
    }
    returntrue;
    }

    staticvoid Main(string[] args)
    {
    Thread t1
    =new Thread(new ThreadStart(ReadProc));
    Thread t2
    =new Thread(new ThreadStart(WriteProc));
    t1.Start();
    t2.Start();

    Thread.Sleep(
    5000);
    Console.WriteLine(
    "按任意键退出...");
    Console.ReadKey();
    }
    }
    }
  • 相关阅读:
    ADO.NET 中的数据并发
    net中前台javascript与后台c#函数相互调用
    js正则函数match、exec、test、search、replace、split使用介绍集合
    jQuery遍历Table tr td td中包含标签
    SQL你必须知道的-查询聚合分组排序
    haut-1280 诡异的迷宫
    int、long long等的取值范围
    codeforce 855B
    nyoj-2357
    codeforces 858A
  • 原文地址:https://www.cnblogs.com/LinFx/p/2123674.html
Copyright © 2020-2023  润新知