2

我一直在研究 WinAPI 中可用的所有不同同步原语,但一直在努力解决本应简单的事情。为什么下面的代码不起作用?

class MultiThreadedCounter
{
private:
    int count; HANDLE hMutex;

public:
    void IncrementCounter()
    {
        if (count == 0)
            hMutex = CreateMutex(NULL, TRUE, NULL);
        count++;
    }

    void DecrementCounter()
    {
        count--;
        if (count == 0)
            ReleaseMutex(hMutex);
    }

    void WaitForCounterToReachZero()
    {
        WaitForSingleObject(hMutex, INFINITE);
        CloseHandle(hMutex);
    }
};
MultiThreadedCounter extractionsInProgressCounter;

它肯定会以正确的顺序被调用。首先,IncrementCounter()在异步任务之前由主线程调用(这里是线程休眠)。然后主线程调用WaitForCounterToReachZero()。最后,后台线程DecrementCounter()在完成工作后调用,这应该允许主线程继续进行。

然而,WaitForSingleObject不是等待。它立即返回,带有WAIT_OBJECT_0. 为什么这样做?这几乎就像最初从未获得过互斥锁一样。但是,在对 的调用中CreateMutex,我设置bInitialOwnerTRUE,这就是为什么我不明白为什么它似乎没有被收购。我想我误解了什么。

谢谢你。

编辑1:

好的,所以为了测试,我改为IncrementCounter()

void IncrementCounter()
{
    if (count == 0)
    {
        hMutex = CreateMutex(NULL, TRUE, NULL);
        DWORD var1 = WaitForSingleObject(hMutex, INFINITE);
        DWORD var2 = WaitForSingleObject(hMutex, INFINITE);
    }
    count++;
}

那真的,真的应该让它陷入僵局,但是不,两个调用都WaitForSingleObject立即返回var1并且var2都等于0(根据标题是WAIT_OBJECT_0)。

调用CreateMutex不能正常工作,可以吗?然而hMutex被设置为一个合理的值并GetLastError()保持为0。所以很困惑......

编辑2:谢谢大家的帮助。我从来没有让这个工作,但是,我现在意识到我做错了。所以我把所有东西都切换到一个事件上,此时它起作用了,然后添加了一些条件来处理无序的递增和递减,然后是一个关键部分来保护计数变量。它有效:)

class MultiThreadedCounter
{
private:
int count; HANDLE hEvent; CRITICAL_SECTION criticalSection;

public:
void IncrementCounter()
{
    EnterCriticalSection(&criticalSection);
    if (count == 0)
        ResetEvent(hEvent);
    count++;
    LeaveCriticalSection(&criticalSection);
}

void DecrementCounter()
{
    EnterCriticalSection(&criticalSection);
    if (count > 0)
        count--;
    if (count == 0)
        SetEvent(hEvent);
    LeaveCriticalSection(&criticalSection);
}

void WaitForCounterToReachZero()
{
    WaitForSingleObject(hEvent, INFINITE);
}

MultiThreadedCounter()
{
    hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
    InitializeCriticalSection(&criticalSection);
    count = 0;
}

~MultiThreadedCounter()
{
    CloseHandle(hEvent);
    DeleteCriticalSection(&criticalSection);
}
};
4

1 回答 1

2

You don't show a constructor for MultiThreadedCounter. Without this, there is no place to initialise count to 0, meaning that the first call to IncrementCounter almost certainly won't call CreateMutex

Your constructor should look something like

MultiThreadedCounter()
    : count(0)
    , hMutex(NULL)
{
}

As an aside, if you need a lock that is used between threads in a single process, you could consider using a critical section instead.

于 2013-08-12T09:13:03.943 回答