当前位置: 首页 > 知识库问答 >
问题:

WinAPI的睡眠在子线程内不工作

司承业
2023-03-14

我是一个初学者,我试图重现一个rae条件,以便使自己熟悉这个问题。为此,我创建了以下程序:

#include <Windows.h>
#include <iostream>

using namespace std;

#define numThreads 1000

DWORD __stdcall addOne(LPVOID pValue)
{
    int* ipValue = (int*)pValue;
    *ipValue += 1;
    Sleep(5000ull);
    *ipValue += 1;
    return 0;
}

int main()
{
    int value = 0;
    HANDLE threads[numThreads];

    for (int i = 0; i < numThreads; ++i)
    {
        threads[i] = CreateThread(NULL, 0, addOne, &value, 0, NULL);
    }

    WaitForMultipleObjects(numThreads, threads, true, INFINITE);

    cout << "resulting value: " << value << endl;
    return 0;
}

我在线程的函数中添加了睡眠,以便重现竞争条件,因为,我是如何理解的,如果我只是添加一个作为工作负载,竞争条件不会表现出来:创建了一个线程,然后它运行工作负载,并且它恰好在另一个迭代中创建的另一个线程开始其工作负载之前完成。我的问题是工作负载中的睡眠()似乎被忽略了。我将参数设置为5sec,我希望程序至少运行5秒,但它会立即完成。当我将睡眠(5000)放在main函数中时,程序会按预期运行(

结果值:1000

而正确答案应该是2000年。你能猜到为什么会发生这种情况吗?

共有2个答案

严心水
2023-03-14

杰里·科芬(Jerry Coffin)给出了正确的答案,但为了避免你输入:

#include <Windows.h>
#include <iostream>
#include <assert.h>

using namespace std;

#define numThreads 1000

DWORD __stdcall addOne(LPVOID pValue)
{
    int* ipValue = (int*)pValue;
    *ipValue += 1;
    Sleep(5000);
    *ipValue += 1;
    return 0;
}

int main()
{
    int value = 0;
    HANDLE threads[numThreads];

    for (int i = 0; i < numThreads; ++i)
    {
        threads[i] = CreateThread(NULL, 0, addOne, &value, 0, NULL);
    }

    DWORD Status = WaitForMultipleObjects(numThreads, threads, true, INFINITE);

    assert(Status != WAIT_FAILED);

    cout << "resulting value: " << value << endl;
    return 0;
}

当出现错误时,请确保已断言任何可能失败的Windows API函数的返回值。如果您确实非常需要等待大量线程,可以通过链接来克服64个线程的限制。一、 例如,每增加64个线程,你就要牺牲一个线程,这个线程的唯一目的就是等待其他64个线程等等。我们(Windows Developer’s Journal)几年前发表了一篇文章来演示这项技术,但我记不起作者的名字了。

易俊驰
2023-03-14

WaitForMultipleObjects一次最多只允许等待MAXIMUM_WAIT_OBJECTS(当前为64个)线程。如果你考虑到这一点:

#include <Windows.h>
#include <iostream>

using namespace std;

#define numThreads MAXIMUM_WAIT_OBJECTS

DWORD __stdcall addOne(LPVOID pValue) {
    int* ipValue=(int*)pValue;
    *ipValue+=1;
    Sleep(5000);
    *ipValue+=1;
    return 0;
}

int main() {
    int value=0;
    HANDLE threads[numThreads];

    for (int i=0; i < numThreads; ++i) {
        threads[i]=CreateThread(NULL, 0, addOne, &value, 0, NULL);
    }

    WaitForMultipleObjects(numThreads, threads, true, INFINITE);

    cout<<"resulting value: "<<value<<endl;
    return 0;
}

…事情比你预期的要多得多。当然,你是否真的会看到比赛条件的结果是一个相当不同的故事——但是在多次运行中,我确实看到结果值略有变化(例如,125左右的低点)。

 类似资料:
  • 我使用 C 和 POSIX 线程创建了一个多线程应用程序。我现在应该阻塞一个线程(主线程),直到设置了布尔标志(变为真)。 我找到了两种方法来完成这件事。 > 在没有睡眠的情况下旋转。 在睡眠中旋转循环。 如果我应该遵循第一种方式,为什么有些人编写代码遵循第二种方式?如果应该使用第二种方法,为什么要让当前线程Hibernate呢?这种方式的缺点是什么?

  • 问题内容: 首先,我想说的是,我知道这个方法是错误的,因此,我出于好奇而问这个问题。可以说我有一个这样的秋千应用程序: 基本上,当我单击按钮时,我期望图像显示,然后GUI冻结2秒钟,然后我期望图像显示。但是发生的是:我单击按钮,GUI冻结2秒钟并显示。没有之前。但是让我感到困惑的是当我把它们和。因此,当我单击按钮时,它会打印“郁金香画”,并在2秒钟后打印“考拉画”。有人可以告诉我这是怎么回事吗?问

  • 我正在调用while循环内的线程Hibernate1秒。当标志为true时,循环将运行(标志为true无限时间)。在循环内,线程应Hibernate1秒,唤醒并增加计数器,检查IF条件,如果为FALSE,则应再次Hibernate1秒并继续29次。在第30次迭代中,IF条件为true,IF语句中调用的方法将收集并存储数据。最后,在第32次迭代中,第二个IF语句将把存储的数据发送到服务器,并将计数设

  • 我正在研究计算机硬件,在那里我们了解到使用硬件计时器比软件延迟获得更准确的结果。我已经在汇编中编写了1毫秒的软件延迟,我可以启动一个进程,使用这个延迟每毫秒重复一次,并使用计数器每100毫秒做一些其他事情,这种技术不如使用我现在要使用的硬件内置的硬件计时器准确。 所以我想知道Java内置的计时有多精确?我们有< code > system . current time millis 和< code

  • 这里的要点是了解实现等待循环的更有效的解决方案,该循环在每次迭代时轮询条件。通过高效,我的意思是“有效的CPU调度”。 我知道代码中使用的等待条件不是“wakeOne”/“wakeAll”指令中使用的“真正的等待条件”,但我想知道对CPU来说,使用假等待条件是否比睡眠更有效。 这里有2个代码片段,它们做同样的事情:等待某些事情发生。这段代码用于工作线程池。因此,当一个线程等待时,其他线程(或其他一

  • 我正在编写一个基于await/sleep范式的网络绑定应用程序。 我更喜欢这样一个答案,不创建任何额外的线程