为什么下面的代码示例导致一个线程执行的方式多于另一个,但是互斥锁不会?
#include <windows.h>
#include <conio.h>
#include <process.h>
#include <iostream>
using namespace std;
typedef struct _THREAD_INFO_ {
COORD coord; // a structure containing x and y coordinates
INT threadNumber; // each thread has it's own number
INT count;
}THREAD_INFO, * PTHREAD_INFO;
void gotoxy(int x, int y);
BOOL g_bRun;
CRITICAL_SECTION g_cs;
unsigned __stdcall ThreadFunc( void* pArguments )
{
PTHREAD_INFO info = (PTHREAD_INFO)pArguments;
while(g_bRun)
{
EnterCriticalSection(&g_cs);
//if(TryEnterCriticalSection(&g_cs))
//{
gotoxy(info->coord.X, info->coord.Y);
cout << "T" << info->threadNumber << ": " << info->count;
info->count++;
LeaveCriticalSection(&g_cs);
//}
}
ExitThread(0);
return 0;
}
int main(void)
{
// OR unsigned int
unsigned int id0, id1; // a place to store the thread ID returned from CreateThread
HANDLE h0, h1; // handles to theads
THREAD_INFO tInfo[2]; // only one of these - not optimal!
g_bRun = TRUE;
ZeroMemory(&tInfo, sizeof(tInfo)); // win32 function - memset(&buffer, 0, sizeof(buffer))
InitializeCriticalSection(&g_cs);
// setup data for the first thread
tInfo[0].threadNumber = 1;
tInfo[0].coord.X = 0;
tInfo[0].coord.Y = 0;
h0 = (HANDLE)_beginthreadex(
NULL, // no security attributes
0, // defaut stack size
&ThreadFunc, // pointer to function
&tInfo[0], // each thread gets its own data to output
0, // 0 for running or CREATE_SUSPENDED
&id0 ); // return thread id - reused here
// setup data for the second thread
tInfo[1].threadNumber = 2;
tInfo[1].coord.X = 15;
tInfo[1].coord.Y = 0;
h1 = (HANDLE)_beginthreadex(
NULL, // no security attributes
0, // defaut stack size
&ThreadFunc, // pointer to function
&tInfo[1], // each thread gets its own data to output
0, // 0 for running or CREATE_SUSPENDED
&id1 ); // return thread id - reused here
_getch();
g_bRun = FALSE;
return 0;
}
void gotoxy(int x, int y) // x=column position and y=row position
{
HANDLE hdl;
COORD coords;
hdl = GetStdHandle(STD_OUTPUT_HANDLE);
coords.X = x;
coords.Y = y;
SetConsoleCursorPosition(hdl, coords);
}
答案 0 :(得分:3)
这可能无法回答您的问题,但关键部分的行为在Windows Server 2003 SP1及更高版本上发生了更改。
如果您有与Windows 7关键部分相关的错误,您无法在XP计算机上重现,则可能会受到该更改的影响。
我的理解是,在Windows XP上,关键部分使用基于FIFO的策略,这对所有线程都是公平的,而后期版本使用旨在减少线程之间上下文切换的新策略。
MSDN page about critical sections
上有关于此的简短说明您可能还想查看this forum post
答案 1 :(得分:2)
关键部分(如互斥锁)旨在保护共享资源免受冲突访问(例如并发修改)。关键部分不意味着替换线程优先级。
您已经人为地引入了共享资源(屏幕)并使其成为瓶颈。因此,关键部分具有很强的竞争力。由于两个线程具有相同的优先级,因此Windows不会选择一个线程而不是另一个线程。减少上下文切换是选择一个线程而不是另一个线程的原因。由于这种减少,共享资源的利用率上升。这是一件好事;这意味着一个线程将在之前完成 lot ,而另一个线程将提前完成。
要以图形方式查看效果,请比较
A B A B A B A B A B
到
AAAAA BBBBB
第二个序列较短,因为从A到B只有一个开关。
答案 2 :(得分:0)
手边浪漫的术语:
CriticalSection说线程希望控件一起做一些事情。
Mutex正在制作一个标记来显示“忙碌”,以便其他人可以等待并通知完成,以便其他人可以启动。其他人已经在等待互斥锁会抓住它,然后再次启动循环并将其恢复。
因此,使用CriticalSection得到的结果是在循环之间无法产生。如果您在Sleep(0);
LeaveCriticalSection
,则可能会有所不同
答案 3 :(得分:0)
我不能说你为什么要观察这种特殊行为,但这可能与每种机制的实现细节有关。我可以说的是,解锁然后立即锁定互斥锁是一件坏事。你最终会观察到奇怪的行为。
答案 4 :(得分:0)
来自某些MSDN文档(http://msdn.microsoft.com/en-us/library/ms682530.aspx):
从带有Service Pack 1(SP1)的Windows Server 2003开始,等待关键部分的线程不会按先到先得的原则获取关键部分。对于大多数代码而言,此更改会显着提高性能