我发现在线代码显示了如何使用redKyle教程中的线程。在“竞争条件”教程中,他基本上展示了如何将两个线程发送到函数。该功能的目的是打印'。'和'#'依次一百次。他提供了使代码工作的代码,他没有提供互斥锁的代码。我修改了代码以包含互斥锁,以防止一个线程访问保存最后一个字符的变量,而另一个线程正在访问它。 我得到了代码工作。大!但是,我一直将睡眠值改为1到50.互斥代码工作正常。但是,当我将睡眠设置为0(或只是将其注释掉)时,互斥锁不再起作用,并且不再以正确的方式打印值(我不再看到严格交替'#'和'。'的200个字符)。
以下是代码:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;
static char lastChar='#';
//define a mutex
HANDLE mutexHandle = NULL;
//flag to specify if thread has begun
bool threadStarted = false;
void threadProc(int *sleepVal, int *threadID)
{
cout<<"sleepVal: "<<*sleepVal<<endl;
for (int i=0; i<100; i++)
{
char currentChar;
threadStarted = true;
while(!threadStarted){}
//lock mutex
WaitForSingleObject(mutexHandle, INFINITE);
if (lastChar == '#')
currentChar = '.';
else
currentChar = '#';
Sleep(*sleepVal);
lastChar = currentChar;
ReleaseMutex(mutexHandle);
threadStarted = false;
// cout<<"\nSleepVal: "<<*sleepVal<<" at: "<<currentChar;
cout<<currentChar;
}//end for
}//end threadProc
int main()
{
cout<<"Race conditions by redKlyde \n";
int sleepVal1 = 50;
int sleepVal2 = 30;
//create mutex
mutexHandle = CreateMutex(NULL, false, NULL);
//create thread1
HANDLE threadHandle;
threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, &sleepVal1, 0, NULL);
//create thread2
HANDLE threadHandle2;
threadHandle2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, &sleepVal2, 0, NULL);
WaitForSingleObject(threadHandle, INFINITE);
WaitForSingleObject(threadHandle2, INFINITE);
cout<<endl<<endl;
CloseHandle(mutexHandle);
system("pause");
return 0;
}
所以我的问题是:为什么将sleep设置为0会使互斥代码无效。
答案 0 :(得分:1)
请注意,您的print语句不受互斥锁保护,因此一个线程可以自由打印而另一个线程可以自由修改。通过不休眠,您允许调度程序根据线程的量来确定打印顺序。
有些事情是错的:
1)你不应该在持有的锁内睡觉。这几乎是不正确的。 2)您的数据共享的任何地方,您应该用锁来保护。这意味着print语句也应该在锁中。
答案 1 :(得分:1)
此外,作为未来使用互斥的提示,在Windows上,最佳用户模式互斥锁是SRWLock,后跟CriticalSection。使用基于句柄的同步对象要慢得多。