为什么睡眠功能会禁用我的互斥锁

Why does Sleep function disable my Mutex

本文关键字:我的 功能 为什么      更新时间:2023-10-16

我在网上找到了显示如何使用 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;
}

所以我的问题是:为什么将睡眠设置为 0 会使互斥代码无效。

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

有些地方不对劲:

1)你不应该睡在有锁的锁里。这几乎永远不正确。2)您的数据被共享的任何地方,您都应该用锁保护。这意味着打印语句也应该在锁中。

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