0

我在 redKyle 的教程中找到了显示如何使用线程的在线代码。在“竞争条件”教程中,他基本上展示了如何将两个线程发送到一个函数。该函数的目标是打印 '.' 和 '#' 依次排列一百次。他提供了使它工作的代码,他没有提供互斥锁的代码。我已经修改了代码以包含互斥锁,以防止一个线程访问保存打印的最后一个字符的变量,而另一个线程正在访问它。我得到了工作的代码。伟大的!但是,我一直在 1 到 50 之间更改睡眠值。互斥锁代码工作正常。然而,

以下是代码:

#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 会使互斥代码无效。

4

2 回答 2

1

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

有一些地方不对:

1)你不应该睡在一个持有的锁里。这几乎是不正确的。2)任何你的数据被共享的地方,你应该用锁守卫。这意味着打印语句也应该处于锁定状态。

于 2012-04-13T18:56:14.453 回答
1

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

于 2012-05-06T17:21:41.890 回答