为什么Sleep功能会禁用我的Mutex

时间:2012-04-13 18:51:54

标签: c++ windows multithreading winapi mutex

我发现在线代码显示了如何使用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会使互斥代码无效。

2 个答案:

答案 0 :(得分:1)

请注意,您的print语句不受互斥锁保护,因此一个线程可以自由打印而另一个线程可以自由修改。通过不休眠,您允许调度程序根据线程的量来确定打印顺序。

有些事情是错的:

1)你不应该在持有的锁内睡觉。这几乎是不正确的。 2)您的数据共享的任何地方,您应该用锁来保护。这意味着print语句也应该在锁中。

答案 1 :(得分:1)

此外,作为未来使用互斥的提示,在Windows上,最佳用户模式互斥锁是SRWLock,后跟CriticalSection。使用基于句柄的同步对象要慢得多。