首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 多線程 WaitForMultipleObjects 返回 87 (WAIT_ABANDONED) 完整分析與修正

     編輯:程式設計綜合問答

現象描述

模擬電影院多廳放映,使用 WaitForMultipleObjects 等待 3 個放映廳 Mutex。運行一段時間後返回 87(即 WAIT_ABANDONED_0 + 1),導致程序異常退出。

根本原因

Mutex 擁有者線程意外終止且未釋放 Mutex。 具體場景:

  1. 線程 B0 佔用 HallMutex[1](廳 2)放映影片 0。
  2. B0 線程結束(觀眾離開),但業務邏輯中 Count[i] == 0 時才釋放 HallMutex[MAP[i]]。
  3. 此時 B0 尚未釋放 Mutex 即結束,系統標記該 Mutex 為「棄用」。
  4. 後續線程 G2 調用 WaitForMultipleObjects 等待 3 個廳 Mutex 時,檢測到 HallMutex[1] 狀態為 WAIT_ABANDONED,返回 87。

錯誤代碼關鍵片段

DWORD index = WaitForMultipleObjects(3, HallMutex, FALSE, -1);
if (index == WAIT_OBJECT_0 || index == WAIT_OBJECT_0+1 || index == WAIT_OBJECT_0+2) {
    // 正常獲得
} else {
    ExitProcess(GetLastError()); // 遇到 ABANDONED 直接退出
}

修正方案

在等待循環中檢測 WAIT_ABANDONED 並重試,而非直接退出:

DWORD index = 0;
bool done = false;
do {
    index = WaitForMultipleObjects(3, HallMutex, FALSE, -1);
    if (index >= WAIT_OBJECT_0 && index < WAIT_OBJECT_0 + 3) {
        MAP[i] = index - WAIT_OBJECT_0;
        // ... 正常邏輯
        done = true;
    } else if (index >= WAIT_ABANDONED_0 && index < WAIT_ABANDONED_0 + 3) {
        // Mutex 被遺棄,視為可用,重新等待
        Sleep(0); // 讓出時間片
    } else if (index == WAIT_FAILED) {
        int e = GetLastError();
        printf("WaitForMultipleObjects failed: %d\n", e);
        ExitProcess(e);
    }
} while (!done);

完整修正代碼

見原帖最佳回答,已將 do-while 迴圈包裹等待邏輯,忽略 WAIT_ABANDONED 並重試。

深度建議

  • 每個放映廳建立專屬管理線程,避免跨線程共享 Mutex 導致擁有權混亂。
  • 使用 std::mutex + std::condition_variable (C++11) 替代原生 API,RAII 自動管理釋放。
  • 嚴格遵循「誰創建誰釋放」或「誰獲取誰釋放」原則,避免線程終止時持有 Mutex。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved