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

多线程随机数生成器程序异常排查与修复求助

双线程随机数生成与显示程序的问题分析及修复

问题描述

需要实现两个线程:

  1. 第一个线程每秒生成5个随机数,持续一分钟(共300个)
  2. 第二个线程每秒显示一个已生成的随机数

现有代码运行后不符合预期,控制台批量输出数字,后续是main函数循环的重复结果。

核心错误点

  • 线程无同步机制:两个线程直接操作全局计数器和数组,存在竞态条件,第二个线程可能读取未生成的数据,输出逻辑混乱。
  • 随机数种子重复初始化:在firstThread的循环内反复调用srand(firstThreadCounter),每次生成随机数前重置种子,导致随机数不随机甚至重复。
  • 输出缓冲区未刷新:cout默认是行缓冲,未手动刷新时会累积输出,导致批量打印;同时误用/t代替\t作为制表符。
  • 循环变量重定义:firstThread内外层循环都用i,内层循环会覆盖外层变量,导致外层循环无法正确执行60次;main函数的嵌套打印循环也存在同样问题。
  • 第二个线程无等待逻辑:直接按固定间隔读取,不管第一个线程是否已经生成对应位置的随机数,可能读取到未初始化的垃圾值。

修复后的代码

#include <iostream>
#include <thread>
#include <cstdlib>
#include <chrono>
#include <mutex>
#include <condition_variable>

#define NUMBER_LIMIT 300
int arr[NUMBER_LIMIT];
static size_t produced = 0, consumed = 0;
std::mutex mtx;
std::condition_variable cv;
bool finished = false;

void producerThread()
{
    // 只初始化一次随机数种子
    srand(time(nullptr));
    for (size_t i = 0; i < 60; i++)
    {
        for (size_t j = 0; j < 5; j++)
        {
            std::lock_guard<std::mutex> lock(mtx);
            arr[produced] = rand();
            produced++;
            // 通知消费者有新数据
            cv.notify_one();
            
            std::this_thread::sleep_for(std::chrono::milliseconds(200));
        }
    }
    // 生产完成后标记状态
    std::lock_guard<std::mutex> lock(mtx);
    finished = true;
    cv.notify_one();
}

void consumerThread()
{
    while (true)
    {
        std::unique_lock<std::mutex> lock(mtx);
        // 等待有新数据或者生产完成
        cv.wait(lock, []{ return produced > consumed || finished; });
        
        if (finished && produced == consumed)
            break; // 生产完成且所有数据已消费,退出
        
        if (produced > consumed)
        {
            std::cout << arr[consumed] << '\t';
            std::cout.flush(); // 立即刷新输出缓冲区
            consumed++;
        }
        lock.unlock();
        
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    std::cout << std::endl;
}

int main()
{
    std::thread producer(producerThread);
    std::thread consumer(consumerThread);

    producer.join();
    consumer.join();

    // 正确遍历并打印所有随机数
    std::cout << "\n所有生成的随机数:\n";
    for (size_t row = 0; row < 30; row++)
    {
        for (size_t col = 0; col < 10; col++)
        {
            size_t idx = row * 10 + col;
            if (idx >= NUMBER_LIMIT)
                break;
            std::cout << arr[idx] << '\t';
        }
        std::cout << '\n';
    }

    return 0;
}

关键改动说明

  1. 线程同步:使用std::mutex保护共享变量(produced、consumed、finished和数组),用std::condition_variable让消费者线程等待新数据生成,避免空读或读取未初始化数据。
  2. 随机数种子初始化:将srand(time(nullptr))移到生产者线程开头,只初始化一次,保证随机数的随机性。
  3. 输出优化:修正制表符为\t,每次输出后调用std::cout.flush(),确保输出实时显示。
  4. 循环变量修正:重命名内外层循环变量(如i和j、row和col),避免变量覆盖导致的逻辑错误。
  5. 消费者逻辑优化:增加循环判断,直到生产完成且所有数据都被消费才退出,保证所有生成的随机数都能被正确输出。

内容的提问来源于stack exchange,提问作者Roma Zinkiv

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:35:21