我正在编写一个多线程程序来计算Fibonacci,Power和Factorial。而不是使用Sleep
,我想等待线程完成,并且我想按照它们完成的顺序显示线程的ID(首先完成,首先显示)。我该怎么做?
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
unsigned int n = 0;
int priorytety[3] = { THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL};
HANDLE watki[3];
DWORD WINAPI Fibbonaci(void *argumenty){
unsigned long long int prevPrev = 0;
unsigned long long int prev = 1;
unsigned long long int wynik = 1;
while (wynik <= n){
wynik = prev + prevPrev;
prevPrev = prev;
prev = wynik;
}
printf("fibbonaci : %llu \n", wynik);
ExitThread(wynik);
//return wynik;
}
DWORD WINAPI Potegi(void *argumenty){
unsigned long long int wynik = 2;
while (wynik <= n){
wynik = wynik << 1;
}
printf("potegi : %llu \n", wynik);
return wynik;
}
DWORD WINAPI Silnia(void *argumenty){
//printf("%d", atoi(argv[argc-1]));
unsigned long long int wynik = 1;
unsigned long long int i = 1;
while (wynik <= n){
wynik = wynik * i;
i = i + 1;
}
printf("silnia : %llu \n", wynik);
return wynik;
}
int main(){
int i;
DWORD id;
system("cls");
scanf_s("%d", &n);
LPTHREAD_START_ROUTINE WINAPI funkcje[3] = { Fibbonaci, Potegi, Silnia };
for (i = 0; i < 3; i++)
{
watki[i] = CreateThread(
NULL, // atrybuty bezpieczeństwa
10000, // inicjalna wielkość stosu
funkcje[i] , // funkcja wątku
(void *)n,// dane dla funkcji wątku
0, // flagi utworzenia
&id);
if (watki[i] != INVALID_HANDLE_VALUE)
{
//printf("Utworzylem watek o identyfikatorze %x\n", id);
// ustawienie priorytetu
SetThreadPriority(watki[i], priorytety[1]);
}
}
Sleep(10000);
getchar();
}
答案 0 :(得分:3)
@WhozCraig是正确的,您应该使用WaitForMultipleObjects()
等待所有线程完成。请阅读this SO post以获取更多信息。
然而,只有当所有人都完成时,它才会告诉你他们结束的顺序。向每个函数添加代码以打印其线程ID应该这样做(使用GetCurrentThreadId()
)。例如:
printf("potegi : %llu, thread ID %ld \n", wynik, GetCurrentThreadId());
现在我们不要忘记printf
语句和线程实际完成之间有时间。你没有在那里做任何工作,但从技术上讲,线程仍然是活跃的。在多线程环境中,无法预测printf
与线程真正终止之间的时间间隔,无论代码有多少。
如果这种差异对您很重要,那么您需要独立加入每个线程并查看哪个线程首先终止。您可以使用零超时重复调用每个线程句柄上的WaitForSingleObject()
,并检测哪个首先终止。是的,如果第三个线程在第二个线程之前稍微完成,而您在检查第一个线程时,则存在轻微的竞争条件,然后检查第二个线程并注意它已终止。你会错过第三个完成的事实。这种轮询技术通过在等待时消耗大量CPU来改变实验。
就我个人而言,我认为你最好只记录每个线程完成计算结果的时间(基于系统时钟),而不是在线程终止时。使用GetTickCount()
或QueryPerformanceCounter()
来衡量时间。