windows - 简单的多线程互斥示例是不正确的

标签 windows winapi visual-c++ mutex waitformultipleobjects

我希望以随机顺序获得从 0 到 4 的数字,但相反,我有一些不同步的困惑

我做错了什么?

#include <iostream>
#include <windows.h>
#include <process.h>

using namespace std;

void addQuery(void *v );

HANDLE ghMutex;

int main()
{
    HANDLE hs[5];
    ghMutex = CreateMutex( NULL, FALSE, NULL);         
    for(int i=0; i<5; ++i)
    {
        hs[i] = (HANDLE)_beginthread(addQuery, 0, (void *)&i);
        if (hs[i] == NULL) 
        {
            printf("error\n"); return -1;
        }
    }

    printf("WaitForMultipleObjects return: %d error: %d\n",
         (DWORD)WaitForMultipleObjects(5, hs, TRUE, INFINITE), GetLastError());


    return 0;
}

void addQuery(void *v )
{
    int t = *((int*)v);
    WaitForSingleObject(ghMutex, INFINITE);

    cout << t << endl;

    ReleaseMutex(ghMutex);
    _endthread();
}

最佳答案

您必须在锁 读取和写入共享变量。您正在锁外读取它,从而使锁变得无关紧要。

但这还不够,因为您的共享变量是一个循环变量,您在没有锁保护的情况下写入该循环变量。一个更好的例子会像这样运行:

#include <iostream>
#include <windows.h>
#include <process.h>

using namespace std;

void addQuery(void *v );

HANDLE ghMutex;
int counter = 0;

int main()
{
    HANDLE hs[5];
    ghMutex = CreateMutex( NULL, FALSE, NULL);         
    for(int i=0; i<5; ++i)
    {
        hs[i] = (HANDLE)_beginthread(addQuery, 0, NULL);
        if (hs[i] == NULL) 
        {
            printf("error\n"); return -1;
        }
    }

    printf("WaitForMultipleObjects return: %d error: %d\n",
         (DWORD)WaitForMultipleObjects(5, hs, TRUE, INFINITE), GetLastError());


    return 0;
}

void addQuery(void *v)
{
    WaitForSingleObject(ghMutex, INFINITE);

    cout << counter << endl;
    counter++;

    ReleaseMutex(ghMutex);
    _endthread();
}

如果可以,请使用临界区而不是互斥锁,因为它们更易于使用且效率更高。但它们具有相同的语义,因为它们只保护锁定 block 内的代码。

注意:Jerry 指出了一些其他问题,但我主要关注高级 trheading 和序列化问题。

关于windows - 简单的多线程互斥示例是不正确的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7841357/

相关文章:

windows - 如何在窗口上设置 HICON(具有多种尺寸的 .ICO)?

c# - 检测鼠标的后退/前进按钮是否被按下

python - Win 64bit GetThreadContext 返回 zeroe'd out 寄存器,或 0x57 错误代码

c# - 检测到 CallbackOnCollectedDelegate

ruby-on-rails - Windows 上 Apache 上的 Rails - HOWTO

c++ - WM_HOTKEY 可以用来模拟热键事件吗?

c++ - 按下 F5 且源代码已过时时启用自动构建

c++ - 错误 C2373 : 'inet_addr' : redefinition; different type modifiers

c++ - 构造错误,调用其方法时找不到对象?

c++ - boost directory_iterator是否在Windows上按字母顺序访问文件和文件夹