我写了一个多线程程序:
#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和任何函数,但我也想知道它们)
答案 0 :(得分:1)
您正在做的事情基本上称为自旋锁,它不应该用于长时间操作。如您所述,这是消耗CPU时间的预期结果。
但是,您可以基于自旋锁和condvar / event构建互斥锁(futex)(快速用户模式互斥锁)。
答案 1 :(得分:1)
您可以使用阻止必须等待的线程的内核API调用,或者可以浪费CPU周期和内存带宽,让您的风扇保持全速运行并保持办公室温暖。
没有其他选择。
答案 2 :(得分:0)
如果我理解你的问题和程序正确,你的程序中有几个问题。其他人也在上面的帖子中提到了这一点。
您的实际关键部分代码非常慢,因为您在文件的新行中写入数字达100000次。文件I / O操作将非常慢,在您的情况下,这是您的线程函数正在执行的操作。我不太了解您在程序中使用的汇编指令,但看起来这些锁定机制代码正在为剩余的线程创建繁忙的等待代码,这些代码尚未安排执行。如上所述,您应该开始使用基于Microsoft的系统上提供的EnterCriticalSection()和LeaveCriticalSection()API。这些API在内部处理任何事情(一般不能从我们自己的逻辑中实现),因此在等待时不会有任何CPU峰值。
如果您仍想使用当前逻辑执行某些操作,我认为您应该使用/实现某种形式的sleep()类型函数,该函数应该执行并尝试。这将确保由于持续执行/检查某些标志而不会出现任何CPU忙时情况。
Calvin还提到你应该尝试分发锁而不是中央锁。我们应该记住一件事,如果我们的任务很简单并且可以通过传统的单线程方法轻松完成,我们就不应该采用多线程解决方案。