You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Windows.h互斥量实现生产者消费者线程的异常问题排查

生产者-消费者线程互斥量协作问题解决

问题原因分析

你的代码存在两个核心错误,导致线程无法正常协作:

  1. 主线程错误占用互斥量:主线程调用WaitForSingleObject(hMutexReady, INFINITE)后,成为hMutexReady的拥有者,但后续生产者线程尝试ReleaseMutex(hMutexReady)时,由于生产者并非该互斥量的拥有者,释放操作无效,导致hMutexReady始终被主线程持有,消费者线程永远无法获取到它,陷入持续等待。
  2. 互斥量初始状态逻辑错误:两个互斥量的初始拥有状态设置不符合生产者-消费者的同步逻辑,导致生产者线程可以无限循环获取hMutexHandled,却无法有效唤醒消费者。

修正后的代码

#include <windows.h>
#include <stdio.h>
#include <iostream>

// 全局互斥量句柄
HANDLE hMutexReady;   // 标记"信息已生成"
HANDLE hMutexHandled; // 标记"信息已处理"

// 全局数据缓冲区(示例)
int g_data = 0;
bool g_exit = false;

// 生产者线程函数
DWORD WINAPI producer(LPVOID param) {
    while (!g_exit) {
        // 等待"信息已处理"互斥量,确保可以生产新数据
        WaitForSingleObject(hMutexHandled, INFINITE);

        // 模拟从用户获取数据
        std::cout << "请输入数据(输入-1退出):";
        std::cin >> g_data;
        if (g_data == -1) {
            g_exit = true;
        }

        // 释放"信息已生成"互斥量,通知消费者可以处理
        ReleaseMutex(hMutexReady);
    }
    return 0;
}

// 消费者线程函数
DWORD WINAPI consumer(LPVOID param) {
    while (!g_exit) {
        // 等待"信息已生成"互斥量,获取待处理数据
        WaitForSingleObject(hMutexReady, INFINITE);

        if (g_exit) {
            break;
        }

        // 模拟处理数据
        std::cout << "处理后的数据:" << g_data * 2 << std::endl;

        // 释放"信息已处理"互斥量,通知生产者可以继续生产
        ReleaseMutex(hMutexHandled);
    }
    // 退出前释放互斥量,避免生产者阻塞
    ReleaseMutex(hMutexHandled);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[]) {
    // 创建互斥量:
    // hMutexReady初始由主线程拥有(消费者初始等待)
    // hMutexHandled初始未被拥有(生产者可立即开始)
    hMutexReady = CreateMutex(NULL, true, NULL);
    hMutexHandled = CreateMutex(NULL, false, NULL);

    // 创建生产者和消费者线程
    HANDLE hProducer = CreateThread(NULL, 0, producer, NULL, 0, NULL);
    HANDLE hConsumer = CreateThread(NULL, 0, consumer, NULL, 0, NULL);

    HANDLE hThread[2] = {hProducer, hConsumer};

    // 等待线程结束
    WaitForMultipleObjects(2, hThread, true, INFINITE);

    // 清理资源
    CloseHandle(hProducer);
    CloseHandle(hConsumer);
    CloseHandle(hMutexReady);
    CloseHandle(hMutexHandled);

    return 0;
}

关键修正点说明

  1. 调整互斥量初始状态:
    • hMutexReady创建时设置bInitialOwner = true,让主线程初始拥有该互斥量,确保消费者线程一开始处于等待状态,直到生产者生产数据后释放它。
    • hMutexHandled保持bInitialOwner = false,让生产者线程可以立即获取,开始第一次生产。
  2. 移除主线程对hMutexReady的错误占用:删除了主线程中WaitForSingleObject(hMutexReady, INFINITE)的调用,避免主线程长期持有该互斥量。
  3. 添加退出逻辑:增加g_exit标记,让用户可以通过输入-1终止程序,避免线程无限循环无法退出。
  4. 确保互斥量正确释放:每个线程仅在成功获取互斥量后才调用ReleaseMutex,保证释放操作的有效性。

内容的提问来源于stack exchange,提问作者Timur Khalikshin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 19:48:13