返回 2026-04-29
⚙️ 工程

跨进程读写锁开发(一):信号量Developing a cross-process reader/writer lock with limited readers, part 1: A semaphore

微软 Raymond Chen 撰写系列文章讲解如何构建一个支持有限读者的跨进程读写锁。本部分介绍使用 Windows 信号量(semaphore)作为基础同步原语的设计思路,解决多个进程间协调读/写访问共享资源的问题。这是实现高性能并发控制的关键第一步。

Raymond Chen

假设你想要实现一个跨进程的读写锁功能,但内置的 SRWLOCK 只能在单个进程内工作。那么,我们能否构建一个支持跨进程的读写锁呢?

为方便说明,假设我们希望最多允许 N 个读者同时读取(N 是一个固定值)。我们可以这样实现:

  • 创建一个计数为 N 的信号量(semaphore),并通过命名或复制句柄的方式在所有相关进程中共享该信号量。
  • 获取读锁时,从信号量中申请一个令牌;释放读锁时,归还该令牌。
  • 获取写锁时,一次性申请 N 个令牌;释放写锁时,归还这 N 个令牌。
  • 写锁的设计思路是:通过占用所有读锁所需的资源(即全部 N 个令牌),确保其他进程无法再获取任何读锁。

    #define MAX_SHARED 100
    HANDLE sharedSemaphore;
    
    void AcquireShared()
    {
        WaitForSingleObject(sharedSemaphore, INFINITE);
    }
    
    void ReleaseShared()
    {
        ReleaseSemaphore(sharedSemaphore, 1, nullptr);
    }
    
    void AcquireExclusive()
    {
        for (unsigned i = 0; i < MAX_SHARED; i++) {
            WaitForSingleObject(sharedSemaphore, INFINITE);
        }
    }
    
    void ReleaseShared()
    {
        ReleaseSemaphore(sharedSemaphore, MAX_SHARED, nullptr);
    }

    由于使用了 WaitForSingleObject 函数,我们还可以设置超时机制,让调用者在无法获取锁时选择放弃操作。

    bool AcquireSharedWithTimeout(DWORD timeout)
    {
        return WaitForSingleObject(sharedSemaphore, timeout) == WAIT_OBJECT_0;
    }
    
    bool AcquireExclusiveWithTimeout(DWORD timeout)
    {
        DWORD start = GetTickCount();
        for (unsigned i = 0; i < MAX_SHARED; i++) {
            DWORD elapsed = GetTickCount() - start;
            if (elapsed > timeout ||
                WaitForSingleObject(sharedSemaphore, timeout - elapsed) == WAIT_TIMEOUT)) {
                // Restore the tokens we already claimed.
                if (i > 0) {
                    ReleaseSemaphore(sharedSemaphore, i, nullptr);
                }
                return false;
            }
        }
        return true;
    }

    独占获取(写锁)较为复杂,因为需要多次调用 WaitForSingleObject,且每次等待时间递减。如果最终超时,则必须提前归还已申请的令牌。

    不过,这里仍然存在一个问题,我们将在下次讨论。

    作者

    Raymond 在 Windows 系统演进过程中已有超过 30 年的参与经验。自 2003 年起,他运营了一个名为 The Old New Thing 的网站,其受欢迎程度远超他的想象,至今仍让他感到些许不安。该网站催生了一本同名书籍《The Old New Thing》(Addison Wesley, 2007)。他偶尔也会出现在 Windows Dev Docs 的 Twitter 账号上,讲述一些毫无实用价值的故事。

    需要完整排版与评论请前往来源站点阅读。