【问题标题】:Simple multithreading mutex example is incorrect简单的多线程互斥锁示例不正确
【发布时间】:2011-10-20 19:44:40
【问题描述】:

我希望以随机顺序获得 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();
}

【问题讨论】:

标签: windows winapi visual-c++ mutex waitformultipleobjects


【解决方案1】:

你必须在锁内部读写共享变量。您在锁之外读取它,从而使锁变得无关紧要。

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

#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();
}

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

注意:Jerry 指出了一些其他问题,但我专注于高级跟踪和序列化问题。

【讨论】:

  • 谢谢!全局int counter 的示例对我来说很清楚。但是我如何将一些数据传递给创建的线程函数?
  • 你传递它的方式和你做的一样,但不是指向循环计数器的指针!!
【解决方案2】:

您的 synchronization 存在一些问题,因为您希望以随机顺序获取 0 到 4 的数字。

问题是变量i写在锁外,每次addQuery方法被线程执行调用,它都会得到变量i的修改版本。这就是为什么您可能会将5 视为所有输出的值。

所以,这是我对这种情况的解决方法。与其在函数addQuery 的参数中传递变量i 的地址,不如传递它的值。希望对您有所帮助:

#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();
}

【讨论】:

    猜你喜欢
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 2012-12-25
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多