C/C++线程详解
一、C语言线程创建(POSIX线程)
1. 基本创建方法
POSIX线程(pthread)是C语言中创建线程的标准API:
#include <pthread.h>
#include <stdio.h>void* thread_func(void* arg) {printf("Thread running with arg: %d\n", *(int*)arg);return NULL;
}int main() {pthread_t tid;int arg = 42;// 创建线程int ret = pthread_create(&tid, NULL, thread_func, &arg);if (ret != 0) {perror("pthread_create failed");return 1;}// 等待线程结束pthread_join(tid, NULL);return 0;
}
2. 关键参数说明
pthread_t *thread
:存储线程ID的指针const pthread_attr_t *attr
:线程属性(NULL表示默认)void *(*start_routine)(void*)
:线程函数指针void *arg
:传递给线程函数的参数
3. 线程属性设置
pthread_attr_t attr;
pthread_attr_init(&attr); // 初始化属性
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 设置分离属性
pthread_create(&tid, &attr, thread_func, NULL);
pthread_attr_destroy(&attr); // 销毁属性对象
二、C++线程创建(std::thread)
1. 基本创建方法
C++11引入了std::thread
类简化线程创建:
#include <iostream>
#include <thread>void thread_function() {std::cout << "Thread function executing" << std::endl;
}int main() {// 创建并启动线程std::thread t(thread_function);// 等待线程结束t.join();return 0;
}
2. 多种创建方式
(1) 使用函数指针
void print_message(const std::string& msg) {std::cout << msg << std::endl;
}std::thread t1(print_message, "Hello from thread");
(2) 使用Lambda表达式
std::thread t2(:ml-search[]{std::cout << "Lambda thread running" << std::endl;
});
(3) 使用成员函数
class MyClass {
public:void member_func() {std::cout << "Member function thread" << std::endl;}
};MyClass obj;
std::thread t3(&MyClass::member_func, &obj);
3. 线程管理
join()
:等待线程结束detach()
:分离线程(后台运行)joinable()
:检查线程是否可join
三、C与C++线程创建对比
特性 | std::thread (C++11) | pthread (POSIX) |
---|---|---|
标准化程度 | C++标准库的一部分 | POSIX标准,非C++原生 |
跨平台性 | 所有支持C++11的平台 | 主要类UNIX系统 |
接口风格 | 面向对象(类+成员函数) | C风格函数接口 |
线程创建 | 构造函数直接启动线程 | 需显式调用pthread_create |
参数传递 | 类型安全,支持任意可调用对象 | 需通过void*指针强制转换 |
资源管理 | RAII自动管理(析构自动处理) | 需手动调用pthread_join/detach |
错误处理 | 异常机制 | 返回值错误码 |
头文件 | <thread> | <pthread.h> |
编译要求 | 需支持C++11 | 需链接-lpthread 库 |
四、实际应用示例
1. 多线程计算(C++)
#include <iostream>
#include <thread>
#include <vector>void compute(int start, int end, int& result) {int sum = 0;for (int i = start; i <= end; ++i) {sum += i;}result = sum;
}int main() {const int n = 1000;int result1, result2;std::thread t1(compute, 1, n/2, std::ref(result1));std::thread t2(compute, n/2+1, n, std::ref(result2));t1.join();t2.join();std::cout << "Total sum: " << result1 + result2 << std::endl;return 0;
}
2. 线程池基础(C)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>#define THREAD_COUNT 4void* worker(void* arg) {int id = *(int*)arg;printf("Worker %d started\n", id);// 实际工作任务...printf("Worker %d finished\n", id);return NULL;
}int main() {pthread_t threads[THREAD_COUNT];int thread_ids[THREAD_COUNT];for (int i = 0; i < THREAD_COUNT; ++i) {thread_ids[i] = i;pthread_create(&threads[i], NULL, worker, &thread_ids[i]);}for (int i = 0; i < THREAD_COUNT; ++i) {pthread_join(threads[i], NULL);}return 0;
}
五、注意事项
- 资源管理:C++的std::thread使用RAII,析构时若未join/detach会terminate
- 参数生命周期:确保线程参数在线程使用期间有效
- 线程安全:共享数据需要同步机制(mutex等)
- 错误处理:C++使用异常,C检查返回值
- 平台差异:pthread在不同Unix-like系统实现可能不同
六、使用建议
-
优先使用std::thread的情况:
- 开发跨平台应用
- 需要与C++其他特性(如lambda、智能指针)集成
- 希望简化资源管理
- 项目已使用C++11或更高标准
-
可能需要使用pthread的情况:
- 维护遗留代码
- 需要特定POSIX线程特性(如优先级控制)
- 在仅支持C的嵌入式环境中开发
- 需要精细控制线程属性(虽然C++11也可通过native_handle实现)
七、性能注意事项
-
在主流平台上,两者性能差异通常小于%5,因为:
std::thread
在Linux上实质是pthread的封装- 线程创建/切换等核心操作最终都调用相同的系统API
-
实际选择应更多考虑:
- 代码可维护性
- 与现有代码库的整合度
- 团队熟悉程度
- 长期维护成本