我的代碼有一個問題:
我的代碼有一個問題。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <windows.h>
#include <string.h>
#include <math.h>
HANDLE事件。
HANDLE mutex。
int runner = 0;
DWORD WINAPI thread_fun(LPVOID lpParam) {
int* data=(int*)lpParam。
for (int j = 0; j < 4; j ) { //this loop necessary in order to reproduction the issue.
if ((data[2] 1) == data[0]) { // if it is last thread /span>
while (1) {
WaitForSingleObject(mutex, INFINITE)。
if (runner == data[0] - 1) { // if all other thread reach event break[/span
ReleaseMutex(mutex)。
break。
}
printf("Run:%d
", runner)。)
ReleaseMutex(mutex)。
Sleep(10) 。
}
printf("Check Done:<<%d>>
", data[2])。)
runner = 0;
PulseEvent(event); //let all other threads continue。
}
else { // if it is not last thread
WaitForSingleObject(mutex, INFINITE)。
runner 。
ReleaseMutex(mutex)。
printf("等待:<<%d>>
", data[2] )。)
WaitForSingleObject(event, INFINITE); //等待直到所有其他執行緒到達這個階段。
printf("Exit:<< %d> >
", data[2] )。)
}
}
return 0;
}
int main()
{
event = CreateEvent(NULL, TRUE, FALSE, NULL)。
mutex = CreateMutex(NULL, FALSE, NULL)。
SetEvent(event)。
int data[3] = {2,8}; //0量執行緒/1量數字。
HANDLE t[10000]。
int ThreadData[1000][3] 。
for (int i = 0; i < data[0]; i ) {
memcpy(ThreadData[i], data, sizeof(int) * 2) 。//將執行緒數量和數字數量復制到執行緒資料中。
ThreadData[i][2] = i; //創建執行緒id。
LPVOID ThreadsData = (LPVOID)(&ThreadData[i])。
t[i] = CreateThread(0, 0, thread_fun, ThreadsData, 0, NULL) 。
if (t[i] == NULL)return 0;
}
while (1) {
DWORD res = WaitForMultipleObjects(data[0], t, true, 1000) 。
if (res != WAIT_TIMEOUT) break;
}
for (int i = 0; i < data[0]; i )CloseHandle(t[i]); //關閉所有執行緒。
CloseHandle(event); //關閉事件。
CloseHandle(mutex); //close mutex。
printf("Done"/span>)。
主要的想法是等待,直到所有的執行緒(除了一個)到達事件并在那里等待,同時最后一個執行緒必須釋放他們的等待。
但是這段代碼并不能可靠地作業。10次中有1次能正確結束,9次只是卡在while(1)。在不同的嘗試中,printf在while(printf("Run:%d
", runner);)列印出不同數量的運行者(0和3)。
問題會是什么呢?
uj5u.com熱心網友回復:
正如我們在評論區發現的那樣,問題在于盡管事件是在無信號的初始狀態下創建的
event = CreateEvent(NULL, TRUE, FALSE, NULL)。
緊接著,它被設定為信號狀態:
它被設定為信號狀態。
SetEvent(event)。
由于這個原因,至少在回圈的第一次迭代中,當j == 0時,第一個作業執行緒不會等待第二個作業執行緒,這導致了race condition。
此外,你的代碼中的以下問題也值得一提(盡管這些問題并不是造成你的問題的原因):
PulseEvent的檔案,不應該使用該函式,因為它可能不可靠,并且主要是為了向后兼容而提供的。根據該檔案,你應該使用條件變數來代替。thread_fun中,最后一個執行緒在一個回圈中鎖定并釋放了mutex。這可能是不好的,因為mutexes不能保證公平,這有可能會導致其他執行緒永遠無法獲得mutex。盡管這種可能性通過你在每個回圈迭代中呼叫Sleep(10);一次而得到緩解,但它仍然不是理想的解決方案。一個更好的解決方案是使用一個條件變數,這樣執行緒只在另一個執行緒實際發出可能發生變化的信號時檢查變數runner的變化。出于性能方面的考慮,這樣的解決方案也會更好。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/320273.html
標籤:
