0

我正在尝试使用 C++、windows 环境中的互锁来实现共享资源管理的单线程写入、多线程读取机制。

Q1。结果代码似乎按我的意图工作,但如果我遗漏了什么,我想请教您的智慧。

Q2。如果有一个真实的生活或良好的主动开源代码示例我可以参考,将不胜感激。

以下是我考虑的目标。

  • 写入只能由单线程执行,并且在写入时必须阻止读取,以避免“不变”中断。
  • 读取可以由多个线程执行。
#include <iostream>
#include <Windows.h>

char g_c = 0i8;

char g_pReadChar[3]{};

void* g_pThreads[4]{};
unsigned long g_pThreadIDs[4]{};

long long g_llLock = 0ULL;          // 0 : Not locked   /   1 : Locked (Writing)    /   2 : Locked (Reading)
long long g_llEntryCount = 0ULL;    // Thread entry count

__forceinline void Read()
{
    // <- if a thread execution is here (case 0)
    InterlockedIncrement64(&g_llEntryCount);
    // <- if a thread execution is here (case 1)

    for (unsigned long long i = 0ULL; i < 100000ULL; ++i)
    {
        if (InterlockedCompareExchange64(&g_llLock, 2LL, 0LL) == 1LL)
        {
            continue;
        }

        // <- if a thread execution is here (case 2)

        // --------------------------------------------------
        // Read data

        std::cout << g_c;

        // --------------------------------------------------

        InterlockedExchange64(&g_llLock, 1LL);  // Lock is needed in order to block case 0

        if (InterlockedDecrement64(&g_llEntryCount) == 0LL)
        {
            InterlockedExchange64(&g_llLock, 0LL);
        }
        else
        {
            InterlockedExchange64(&g_llLock, 2LL);
        }

        return;
    }

    InterlockedDecrement64(&g_llEntryCount);
}

__forceinline unsigned long __stdcall ReadLoop(void* _pParam)
{
    while (true)
    {
        Read();
        Sleep(1);
    }
}

__forceinline void Write(const unsigned long long _ullKey)
{
    for (unsigned long long i = 0ULL; i < 100000ULL; ++i)
    {
        if (InterlockedCompareExchange64(&g_llLock, 1LL, 0LL) != 0LL)
        {
            continue;
        }

        // --------------------------------------------------
        // Write data

        if (_ullKey == 0ULL)
        {
            g_c = 'A';
        }
        else if (_ullKey == 1ULL)
        {
            g_c = 'B';
        }
        else
        {
            g_c = 'C';
        }

        // --------------------------------------------------

        InterlockedExchange64(&g_llLock, 0LL);

        return;
    }
}

__forceinline unsigned long __stdcall WriteLoop(void* _pParam)
{
    unsigned long long ullCount = 0ULL;
    unsigned long long ullKey = 0ULL;
    while (true)
    {
        if (ullCount > 10000ULL)
        {
            ++ullKey;
            if (ullKey >= 3ULL)
            {
                ullKey = 0ULL;
            }
            ullCount = 0ULL;
        }

        Write(ullKey);
        ++ullCount;
    }
}

int main()
{
    g_pThreads[0] = CreateThread(nullptr, 0ULL, ReadLoop, nullptr, 0UL, &g_pThreadIDs[0]);
    g_pThreads[1] = CreateThread(nullptr, 0ULL, ReadLoop, nullptr, 0UL, &g_pThreadIDs[1]);
    g_pThreads[2] = CreateThread(nullptr, 0ULL, ReadLoop, nullptr, 0UL, &g_pThreadIDs[2]);
    g_pThreads[3] = CreateThread(nullptr, 0ULL, WriteLoop, nullptr, 0UL, &g_pThreadIDs[3]);

    Sleep(100000);

    return 0;
}
4

0 回答 0