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

线程在condition_variable.wait()处持续挂起的问题解决咨询

解决多线程Stack监控线程冻结与安全终止问题

核心问题分析

你的代码存在几个关键问题导致线程冻结和程序异常:

  1. 文件流提前关闭:WriteStack循环内每次写完就调用outFile.close(),第一次执行后文件流就处于失效状态,后续触发的写入操作完全无效,同时这个操作毫无必要——文件流应该在析构时统一关闭。
  2. 无线程退出信号:线程在while(true)中无限等待条件变量,main结束时析构函数调用join(),但线程永远卡在cv.wait()无法退出,导致程序冻结。
  3. 路径转义错误:原代码中的文件路径"C:\Users\mayday\Desktop\stack.txt"里的反斜杠未转义,会被编译器解析为无效转义字符(比如\U),必须改为双反斜杠或者正斜杠。
  4. 条件变量等待逻辑缺失退出判断:仅判断head != prevHead,线程无法感知程序终止信号,必须结合退出标志调整谓词。

修改后的代码

#include <iostream>
#include <fstream>

#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>

struct Node {
    int data;
    Node* next;
};

class Stack {
private:
    Node* head;
    std::mutex mtx;
    std::thread writeThread;
    std::ofstream outFile;
    Node* prevHead;
    std::condition_variable cv;
    std::atomic<bool> stopFlag; // 线程退出标志

public:
    Stack() : head(nullptr), prevHead(nullptr), stopFlag(false) {
        // 修复路径转义问题
        outFile.open("C:\\Users\\mayday\\Desktop\\stack.txt");
        writeThread = std::thread(&Stack::WriteStack, this);
    }

    ~Stack() {
        // 设置退出标志并通知线程
        stopFlag = true;
        cv.notify_one();
        // 等待线程退出
        if (writeThread.joinable()) {
            writeThread.join();
        }
        // 统一关闭文件流
        if (outFile.is_open()) {
            outFile.close();
        }
        // 额外:释放Stack的节点内存,避免内存泄漏
        Node* temp = head;
        while (temp != nullptr) {
            Node* next = temp->next;
            delete temp;
            temp = next;
        }
    }

    void Push(int data) {
        std::unique_lock<std::mutex> lock(mtx);
        Node* newNode = new Node();
        newNode->data = data;
        newNode->next = head;
        head = newNode;
        lock.unlock();
        cv.notify_one();
    }

    void WriteStack() {
        while (!stopFlag) { // 以退出标志作为循环条件
            std::unique_lock<std::mutex> lock(mtx);
            // 等待:要么收到退出信号,要么head发生变化
            cv.wait(lock, [this]() { 
                return stopFlag || head != prevHead; 
            });

            if (stopFlag) {
                break; // 收到退出信号,直接退出循环
            }

            // 写入文件逻辑
            Node* temp = head;
            while (temp != nullptr) {
                outFile << temp->data << " ";
                temp = temp->next;
            }
            outFile << std::endl;
            prevHead = head;
        }
    }
};

int main() {
    Stack s;
    s.Push(1);
    s.Push(2);
    s.Push(3);
    return 0;
}

关键修改说明

  • 添加stopFlag原子变量:用原子变量保证线程间的可见性,析构时设置为true并通知线程,让线程能跳出循环。
  • 调整条件变量谓词:wait的判断逻辑同时包含退出标志和head变化,线程既能响应Stack更新,也能及时收到终止信号。
  • 文件流管理优化:把outFile.close()移到析构函数,避免提前关闭导致后续写入失效。
  • 修复路径转义:将路径中的反斜杠改为双反斜杠,确保文件能正常打开。
  • 内存泄漏修复:析构时释放Stack的所有节点内存,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Space Time

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:35:26