windows 简单的多线程互斥示例不正确
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7841357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple multithreading mutex example is incorrect
提问by triclosan
I expect to get numbers from 0 to 4 in random order, but instead, I have some unsynchronized mess
我希望以随机顺序获得从 0 到 4 的数字,但相反,我有一些不同步的混乱
What i do wrong?
我做错了什么?
#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();
}
回答by David Heffernan
You have to read and write the shared variable insidethe lock. You are reading it outside of the lock and thus rendering the lock irrelevant.
您必须在锁内读取和写入共享变量。您正在锁之外读取它,从而使锁变得无关紧要。
But even that's not enough since your shared variable is a loop variable that you are writing to without protection of the lock. A much better example would run like this:
但即使这样还不够,因为您的共享变量是一个循环变量,您在没有锁保护的情况下写入该变量。一个更好的例子会像这样运行:
#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();
}
If you can, use a critical section rather than a mutex because they are simpler to use and more efficient. But they have the same semantics in that they only protect code inside the locking block.
如果可以,请使用临界区而不是互斥锁,因为它们更易于使用且更高效。但是它们具有相同的语义,因为它们只保护锁定块内的代码。
Note: Jerry has pointer out some other problems, but I've concentrated on the high level trheading and serialization concerns.
注意:Jerry 指出了一些其他问题,但我专注于高层次的 trheading 和序列化问题。
回答by waty
Your synchronization
has some issues as you want to get numbers from 0 to 4 in random order.
您synchronization
有一些问题,因为您想以随机顺序获取从 0 到 4 的数字。
The problem is that the variable i
is write outside the lock and every time the addQuery
method get called by the execution of a thread, it get the modified version of variable i
. That why you may see 5
as the value at the output for all.
问题是变量i
被写在锁外,每次addQuery
线程执行调用该方法时,它都会获得变量的修改版本i
。这就是为什么您可能会看到5
所有输出的值。
So, here is my fix for this scenario. Instead of pass the address of variable i
in parameters of the function addQuery
, you should pass it's value. Hope it helps:
所以,这是我对这种情况的修复。您应该传递它的值,而不是i
在函数的参数中传递变量的地址addQuery
。希望能帮助到你:
#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();
}