很多人在 CentOS 上第一次尝试 C++ 多线程,卡住的往往不是代码本身,而是编译器版本和链接参数。本文按“环境检查、示例代码、编译运行、扩展选择”四个部分展开,帮助你判断 CentOS 7 是否具备运行条件,也说明为什么 -pthread 和 join() 这类细节不能省略。
先确认 CentOS 7 的 GCC 是否够新
在 CentOS 上使用 C++11 标准库里的 <thread>,前提是编译器版本不能太旧。CentOS 7 自带的 GCC 通常低于 4.8,这种环境下直接编译多线程示例,往往会因为标准库支持不足而失败。
比较直接的做法,是通过 SCL(Software Collections)安装较新的工具链。原文给出的命令如下:
sudo yum install centos-release-scl
sudo yum install devtoolset-7
scl enable devtoolset-7 bash
这里安装的是 GCC 7 系列,已经足够覆盖本文示例。执行 scl enable devtoolset-7 bash 之后,新的 GCC 只在当前终端会话中生效,这一点需要特别注意:如果你换了一个终端重新编译,就需要再次启用。
用一个最小示例验证线程库是否可用
环境准备好之后,可以先写一个最小测试文件,例如 multithread_example.cpp。这个示例只做一件事:由主线程创建一个子线程,子线程输出一句话,随后主线程等待它结束。

#include <iostream>
#include <thread>
void hello_function() {
std::cout << "Hello from a thread!" << std::endl;
}
int main() {
// 创建一个线程
std::thread t(hello_function);
// 等待线程完成
t.join();
std::cout << "Hello from the main function!" << std::endl;
return 0;
}
这段代码的核心是 std::thread t(hello_function);,它会启动一个新线程去执行 hello_function。随后调用 t.join(),表示主线程会等待子线程执行完毕再继续向下运行。
这里有一个容易被忽略的点:线程对象在结束前必须显式处理。原文已经提到,至少要调用 join() 或者 detach(),否则程序退出时会崩溃。对于这种教学示例,join() 更直观,也更适合确认执行顺序。
编译时为什么一定要加 -pthread
示例文件写好后,编译命令不能只写标准版本,还要带上线程参数:

g++ -std=c++11 -pthread multithread_example.cpp -o multithread_example
这条命令里有两个关键点:
1. -std=c++11 用来启用 C++11 标准
<thread> 属于 C++11 标准库的一部分,如果不启用这个标准,编译器可能无法识别相关接口。
2. -pthread 负责线程支持与链接
-pthread 不是可有可无的附加项,它会告诉编译器和链接器启用 POSIX 线程相关支持。少了这个参数,常见结果就是链接报错,即使源码本身没有语法问题,也无法生成可执行文件。

编译完成后,直接运行程序:
./multithread_example
正常情况下,输出会包含两行:
Hello from a thread!
Hello from the main function!
两行内容的出现顺序在更复杂的多线程程序里未必固定,但在这个示例中,主线程会在 join() 之后才继续执行,因此可以把它看成一次最基础的线程创建与回收验证。
跑通之后,还能继续用哪些并发组件
如果你的目标不只是“创建一个线程”,那么仅有 <thread> 还不够。C++11 标准库已经提供了几类常用并发工具,可以直接继续往下扩展:
std::mutex:用于保护共享数据,避免多个线程同时写入造成竞争。std::condition_variable:用于线程间等待与通知,适合生产者/消费者模型。std::future:用于获取异步任务结果,减少手动管理状态的负担。
这些组件和 <thread> 配合使用,已经能够覆盖大部分常见的 Linux 多线程开发场景。对于一般项目来说,先把标准库方案用熟,通常比一开始就引入额外框架更省心。
标准库和 Boost.Thread 怎么选
在 CentOS 上,除了 C++11 标准库,也可以使用 Boost.Thread。它的优势是出现更早、在一些历史项目中更常见,跨平台兼容性也一直不错;但代价是需要额外安装 Boost 库,并增加依赖管理成本。
如果你的项目本身已经依赖 Boost,那么继续使用 Boost.Thread 是合理选择;如果没有这层前提,直接使用标准库通常更合适。原因很简单:本文示例所需的线程能力,C++11 已经原生提供,不必为了一个基础并发需求再额外引入一套库。













