如何解决忙等待许多正在运行的线程

时间:2014-03-17 07:21:49

标签: c++ multithreading visual-c++ assembly c++11

我写了一个多线程程序:

#include <Windows.h>
#include <process.h>
#include <stdio.h>
#include <fstream>
#include <iostream>
using namespace std;
ofstream myfile;
BYTE lockmem=0x0;
unsigned int __stdcall mythreadA(void* data) 
{
    __asm
    {
        mov DL,0xFF
        mutex:
        mov AL,0x0
        LOCK CMPXCHG lockmem,DL
        jnz mutex
    }

    // Enter Critical Section
    for (int i = 0; i < 100000; i++) 
    {
        myfile << "." << i << endl;
    }
    // Exit Critical Section
    __asm
    {
    lock not lockmem
    }
    return 0;
}

int main(int argc, char* argv[])
{
    myfile.open ("report.txt");
    HANDLE myhandleA[10];
    //int index = 0;
    for(int index = 0;index < 100;index++)
    {
        myhandleA[index] = (HANDLE)_beginthreadex(0, 0, &mythreadA, 0, 0, 0);
    }
    getchar();
    myfile.close();
    return 0;
}

在关键部分我编写内联代码以确保只有一个线程在关键部分。(在这个程序中我不想使用API​​和函数来实现关键部分中唯一的一个线程所以我使用内联汇编)。现在我忙着等待问题。因为在一个线程进入临界区之后,其他线程在关键部分之前忙于循环,所以cpu的进程上升了!在这里,我寻找解决忙碌等待问题的方法。 (我更喜欢使用汇编指令而不是API和任何函数,但我也想知道它们)

3 个答案:

答案 0 :(得分:1)

您正在做的事情基本上称为自旋锁,它不应该用于长时间操作。如您所述,这是消耗CPU时间的预期结果。

但是,您可以基于自旋锁和condvar / event构建互斥锁(futex)(快速用户模式互斥锁)。

答案 1 :(得分:1)

您可以使用阻止必须等待的线程的内核API调用,或者可以浪费CPU周期和内存带宽,让您的风扇保持全速运行并保持办公室温暖。

没有其他选择。

答案 2 :(得分:0)

如果我理解你的问题和程序正确,你的程序中有几个问题。其他人也在上面的帖子中提到了这一点。

  • 您的实际关键部分代码非常慢,因为您在文件的新行中写入数字达100000次。文件I / O操作将非常慢,在您的情况下,这是您的线程函数正在执行的操作。我不太了解您在程序中使用的汇编指令,但看起来这些锁定机制代码正在为剩余的线程创建繁忙的等待代码,这些代码尚未安排执行。如上所述,您应该开始使用基于Microsoft的系统上提供的EnterCriticalSection()和LeaveCriticalSection()API。这些API在内部处理任何事情(一般不能从我们自己的逻辑中实现),因此在等待时不会有任何CPU峰值。

  • 如果您仍想使用当前逻辑执行某些操作,我认为您应该使用/实现某种形式的sleep()类型函数,该函数应该执行并尝试。这将确保由于持续执行/检查某些标志而不会出现任何CPU忙时情况。

  • Calvin还提到你应该尝试分发锁而不是中央锁。我们应该记住一件事,如果我们的任务很简单并且可以通过传统的单线程方法轻松完成,我们就不应该采用多线程解决方案。