您当前的位置: 首页 >  .net

寒冰屋

暂无认证

  • 4浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

.NET读写锁的最简单实现

寒冰屋 发布时间:2022-05-23 20:00:00 ,浏览量:4

  • 下载源代码 - 1.4 KB
介绍

标准Monitor.Wait和Monitor.PulseAll方法现在很少使用,但仍然可以提供强大的线程同步能力。如前所述,我们将实现一个标准的读写器锁,所以让我们直接深入代码:

private readonly object syncRoot = new object();
private readonly object syncWrite = new object();

// A number of acive readers.
private int rcount = 0;

// A total number of pending and active writers.
private int wcount = 0;

没错,我们只需要两个计数器——一个用于每个所有者类型,两个用于同步的根对象。接下来,让我们探索EnterXXXLock部分:

public void EnterReadLock()
{
    lock (syncRoot)
    {
        while (wcount > 0)
        {
            Monitor.Wait(syncRoot); // Wait till all writers are done.
        }

        rcount++; // Notify that there is an active reader.
    }
}

public void EnterWriteLock()
{
    lock (syncRoot)
    {
        wcount++; // Notify that there is a pending writer.

        while (rcount > 0)
        {
            Monitor.Wait(syncRoot); // Wait till all readers are done.
        }
    }

    Monitor.Enter(syncWrite);
}

该EnterReadLock方法仅允许读者在reader未访问资源时继续。反过来,该EnterWriteLock方法会立即通知writer的存在,然后等待reader释放锁。从技术上讲,这段代码将传入的请求分成两大组writer和reader,前者优先。因此,我们需要一个额外的调用Monitor.Enter(syncWrite)来确保在给定的时间只有一个writer可以访问。以下发布逻辑:

public void ExitReadLock()
{
    lock (syncRoot)
    {
        if (--rcount == 0 && wcount > 0)
        {
            Monitor.PulseAll(syncRoot); // Notify writers waiting.
        }
    }
}

public void ExitWriteLock()
{
    Monitor.Exit(syncWrite);

    lock (syncRoot)
    {
        if (--wcount == 0)
        {
            Monitor.PulseAll(syncRoot); // Notify readers waiting.
        }
    }
}

连续的最后一个reader或writer只是唤醒所有等待的线程,以便他们可以继续比赛。为了演示这是如何工作的,我创建了一个控制台应用程序,它运行多个线程同时访问同一资源。这是应用程序生成的示例输出:

源代码可在此链接下载。只需解压缩并执行dotnet run命令即可。

https://www.codeproject.com/Tips/5323262/The-Simplest-Implementation-of-a-Reader-Writer-Loc

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.1314s