闪光阳 2015-06-30 00:33 采纳率: 100%
浏览 2574
已采纳

C++多线程WaitForMultipleObject 返回值为87 怎么回事

我贴一下我的代码,为什么会出现返回87的问题

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <windows.h>
#include <map>
using namespace std;

#define random   (rand()*1000)/RAND_MAX // random audience
int movieNumber;
int Count[1000];
HANDLE Mutex[1000];
HANDLE HallMutex[3];
map<int ,DWORD >MAP;

DWORD WINAPI VideoShow(LPVOID vid) {
    int i = (int)vid;
    printf("来个一个观众,想看%d影片\n",i);
    WaitForSingleObject(Mutex[i],-1);
        Count[i]++;
        if (Count[i] == 1) {
            DWORD index = WaitForMultipleObjects(3,HallMutex,FALSE,-1);
            if (index == WAIT_OBJECT_0 || index == WAIT_OBJECT_0 + 1 || index == WAIT_OBJECT_0 + 2) {
                MAP[i] = index - WAIT_OBJECT_0;
                printf("观众进入录像厅\n");
                printf("录像厅%d正在放映影片%d,有%d个观众\n",index,i,1);
            }
            else {
                ExitProcess(GetLastError());
            }
        }
        else {
            printf("观众进入录像厅\n");
            printf("录像厅%d正在放映影片%d,有%d个观众\n",MAP[i],i,Count[i]);
        }
    ReleaseMutex(Mutex[i]);
    Sleep(2000);
    WaitForSingleObject(Mutex[i],-1);
        Count[i]--;
        printf("有一个观众从正在播放影片%d的录像厅%d离开,还有%d个人\n",i,MAP[i],Count[i]);
        if (Count[i] == 0) {
            printf("录像厅%d放映结束\n",MAP[i]);
            ReleaseMutex(HallMutex[MAP[i]]);
        }
    ReleaseMutex(Mutex[i]);
}

int main () {
    printf("请输入电影院里电影的数目\n");
    cin >> movieNumber;
    for (int i = 0;i < 3;i++) {
        HallMutex[i] = CreateMutex(NULL,0,NULL);
    }
    for (int i = 0;i < movieNumber;i++) {
        Mutex[i] = CreateMutex(NULL,0,NULL);
    }
    HANDLE hThread;
    while (1) {
        Sleep(random);
        DWORD a = rand() % movieNumber;
        hThread = CreateThread(NULL,0,VideoShow,LPVOID(a),0,NULL);
    }
}
  • 写回答

6条回答 默认 最新

  • 知常曰明 2015-06-30 12:08
    关注

    如oyljerry所说,你的129是WAIT_ABANDONED_0+1
    这个是指:有一个Mutex,它的拥有者线程已经结束,但是那个线程没有释放Mutex。
    为此,我以5执行了你的代码,结果如下

    请输入电影院里电影的数目
    5
    来个一个观众,想看2影片
    观众进入录像厅
    录像厅0正在放映影片2,有1个观众
    来个一个观众,想看0影片
    观众进入录像厅
    录像厅1正在放映影片0,有1个观众
    来个一个观众,想看4影片
    观众进入录像厅
    录像厅2正在放映影片4,有1个观众
    来个一个观众,想看3影片
    来个一个观众,想看4影片
    观众进入录像厅
    录像厅2正在放映影片4,有2个观众
    有一个观众从正在播放影片2的录像厅0离开,还有0个人
    录像厅0放映结束
    观众进入录像厅
    录像厅0正在放映影片3,有1个观众
    来个一个观众,想看0影片
    观众进入录像厅
    录像厅1正在放映影片0,有2个观众
    有一个观众从正在播放影片0的录像厅1离开,还有1个人
    有一个观众从正在播放影片4的录像厅2离开,还有1个人
    来个一个观众,想看2影片
    LastError = 87
    
    

    打印LastError的位置就是出现129的时候,经分析,执行的线程情况如下,其中A.B.C...代表来的人(在本例中相当于线程),1,2,3代表影片编号

    +-等--+-1厅-+-2厅-+-3厅-+
    | A2--|->A2 |     |     |
    | B0--|-----|->B0 |     |
    | C4--|-----|-----|->C4 |
    | D3  |     |     |     |
    | E4--|-----|-----|->E4 |
    | A2<-|--A2 |     |     |
    | D3--|->D3 |     |     |
    | F0--|-----|->F0 |     |
    | B0<-|-----|--B0 |     |
    | C4<-|-----|-----|--C4 |
    | G2  |     |     |     |ERROR
    

    由此可见在F0来看电影之后,B0离开了电影院.而2厅的Mutex是B0线程创建的.因此它退出但是没有ReleaseMutex(当然是因为业务如此)
    然后到G2的时候,需要找一个厅时,就会报129(WAIT_ABANDONED_0+1)
    解决方法,对如题的简单应用来说,可以直接忽略WAIT_ABANDONED_0这组数据重新等待,因此把代码略改一下,如下所示

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <windows.h>
    #include <map>
    using namespace std;
    
    #define random   (rand()*1000)/RAND_MAX // random audience
    int movieNumber;
    int Count[1000];
    HANDLE Mutex[1000];
    HANDLE HallMutex[3];
    map<int, DWORD >MAP;
    
    DWORD WINAPI VideoShow(LPVOID vid) {
        int i = (int)vid;
        printf("来个一个观众,想看%d影片\n", i);
        WaitForSingleObject(Mutex[i], -1);
        Count[i]++;
        if (Count[i] == 1) {
            DWORD index = 0;
            bool done = false;
            do
            {
                index = WaitForMultipleObjects(3, HallMutex, FALSE, -1);
                if (index == WAIT_OBJECT_0 || index == WAIT_OBJECT_0 + 1 || index == WAIT_OBJECT_0 + 2) {
                    MAP[i] = index - WAIT_OBJECT_0;
                    printf("观众进入录像厅\n");
                    printf("录像厅%d正在放映影片%d,有%d个观众\n", index, i, 1);
                    done = true;
                }
                else if (index == 0xFFFFFFFF)
                {
                    int e = GetLastError();
                    printf("LastError = %d\n", e);
                    ExitProcess(e);
                }
                else
                {
                    Sleep(0);
                }
            } while (!done);
        }
        else {
            printf("观众进入录像厅\n");
            printf("录像厅%d正在放映影片%d,有%d个观众\n", MAP[i], i, Count[i]);
        }
        ReleaseMutex(Mutex[i]);
        Sleep(2000);
        WaitForSingleObject(Mutex[i], -1);
        Count[i]--;
        printf("有一个观众从正在播放影片%d的录像厅%d离开,还有%d个人\n", i, MAP[i], Count[i]);
        if (Count[i] == 0) {
            printf("录像厅%d放映结束\n", MAP[i]);
            ReleaseMutex(HallMutex[MAP[i]]);
        }
        ReleaseMutex(Mutex[i]);
    }
    
    int main() {
        printf("请输入电影院里电影的数目\n");
        cin >> movieNumber;
        for (int i = 0; i < 3; i++) {
            HallMutex[i] = CreateMutex(NULL, 0, NULL);
        }
        for (int i = 0; i < movieNumber; i++) {
            Mutex[i] = CreateMutex(NULL, 0, NULL);
        }
        HANDLE hThread;
        while (1) {
            Sleep(random);
            DWORD a = rand() % movieNumber;
            hThread = CreateThread(NULL, 0, VideoShow, LPVOID(a), 0, NULL);
        }
    }
    

    对于较复杂的情况,这样使用可能引起其他的同步问题。在这样的情况下,建议对每个放映厅创建线程,单独管理。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 请问一下这个运行结果是怎么来的
  • ¥15 这个复选框什么作用?
  • ¥15 单通道放大电路的工作原理
  • ¥30 YOLO检测微调结果p为1
  • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下