用std::thread分段打印易出错,因std::cout非线程安全且i++非原子操作,需用std::atomic_int保证计数、std::mutex保护输出,或纯互斥锁方案,避免竞态与输出粘连。

用 std::thread 分段打印容易出错?先看同步问题
直接用多个 std::thread 各自循环打印,大概率输出乱序甚至重复/跳号——因为没有保护共享的计数器或输出流。C++ 标准输出 std::cout 本身不是线程安全的,多个线程同时写会崩。
- 别用全局变量 + 多线程裸递增:
i++不是原子操作,竞态条件必现 - 别对
std::cout做无保护调用:即使数字没错,换行也可能粘连(比如 “12\n34\n” 变成 “1234\n\n”) - 分段任务(如线程0打1-25、线程1打26-50)可行,但必须提前算好边界,且不能依赖运行时动态取号
std::atomic_int + 互斥锁双保险最稳
既要保证计数器不冲突,又要确保每次 std::cout 输出完整。推荐组合:用 std::atomic_int 管数字,用 std::mutex 护输出。
#include <thread>
#include <mutex>
#include <atomic>
#include <iostream>
std::atomic_int counter{1};
std::mutex cout_mutex;
void print_worker() {
while (true) {
int n = counter.fetch_add(1, std::memory_order_relaxed);
if (n > 100) break;
std::lock_guard<:mutex> lock(cout_mutex);
std::cout
<p>注意:<code>fetch_add</code> 返回旧值,所以判断 <code>n > 100</code> 才退出;<code>std::memory_order_relaxed</code> 足够,因为仅需计数不依赖其他内存操作。</p>
<h3>只用 <code>std::mutex</code> 也行,但性能稍低</h3>
<p>如果不想引入原子操作,纯靠锁也能做,只是每次都要抢锁——包括读和改计数器,比原子操作重。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>定义 <code>int counter = 1</code> 和 <code>std::mutex mtx</code>
</li>
<li>每次循环:加锁 → 读 <code>counter</code> → 判断是否 ≤100 → 输出 → <code>counter++</code> → 解锁</li>
<li>缺点:锁竞争更频繁,尤其线程多时,可能卡在锁上等半天</li>
</ul>
<h3>为什么不用 <code>std::condition_variable</code>?</h3>
<p>这题不需要唤醒等待、也不需要精确调度顺序。条件变量适合“等某个条件成立再干活”,比如“等缓冲区有数据再消费”。而本题是“抢着干完100个活”,用原子+锁或纯锁更直白高效。</p>
<p>强行套 <code>std::condition_variable</code> 反而增加复杂度:要维护状态变量、虚假唤醒处理、额外 notify 开销——没收益还易写错。</p>
<p>真正要注意的是:线程数别设太多(比如开100个线程打100个数),上下文切换开销会吃掉所有优势;2~4个线程足够。</p></:mutex></iostream></atomic></mutex></thread>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










