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
-
实际选择应更多考虑:
- 代码可维护性
- 与现有代码库的整合度
- 团队熟悉程度
- 长期维护成本
相关文章:
C/C++线程详解
一、C语言线程创建(POSIX线程) 1. 基本创建方法 POSIX线程(pthread)是C语言中创建线程的标准API: #include <pthread.h> #include <stdio.h>void* thread_func(void* arg) {printf("Thread runnin…...

红队系列-网络安全知识锦囊-CTF(持续更新)
CTF CTF系列-AWD专题篇CTF-比赛培训基础1 CTF 介绍HTTP协议分析进阶001.CTF简介_宽字节注入高级 2018CTF——黑客大赛特训CTF-PWNPWNCTF竞赛中的主要题型之一了解CTF Capture The Flag 夺旗描述:# gets从标准输入设备读字符串函数#下面是对main函数中的汇编代码的解释:modifi…...

Windows环境下常用网络命令使用
ipconfig命令使用: ipconfig可用于显示当前的TCP/IP配置的设置值,通常是用来检验人工配置的TCP/IP设置是否正确。在网络连接出现问题时,可以使用ipconfig /release和ipconfig /renew命令来刷新IP地址,这通常能解决因IP地址冲突或…...

双系统下 ubuntu 20.04 突然 开机黑屏报错 hdaudioC0D2: unable to configure disabling
双系统下 ubuntu 20.04 突然 开机黑屏报错 hdaudioC0D2: unable to configure disabling 简介:今天在开实验室开双系统台式机时,ubuntu 20.04 系统下,突然在某次关机后再开机时,本来启动好好的,但是在进行图形化启动时,本来应该是显示输入账号和密码时,直接黑屏报错了,…...
easyExcel导入导出convert
easyExcel版本2.2.7,3.0及以上使用不一致 类上加注解 ExcelProperty(value "下发类型",converter ComponentPurchaseBomExceladvanceStatusConvert.class)private Integer advanceStatus; 转换类 import com.alibaba.excel.converters.Converter; impo…...
C语言高频面试题——指针函数和函数指针的区别
在 C 语言中,指针函数 和 函数指针 是两个容易混淆的概念,但它们的功能和用途完全不同。以下是详细的对比分析,帮助你彻底理解它们的区别。 1. 指针函数(Function Returning a Pointer) 定义 指针函数 是一个返回值为…...

软考中级-软件设计师 知识点速过1(手写笔记)
第一章:数值及其转换 没什么可说的,包括二进制转八进制和十六进制 第二章:计算机内部数据表示 真值和机器数: 原码(后面都拿x -19举例) : 反码: 补码: 移码: 定点数…...
【美化vim】
美化vim 涉及文件一个例子 涉及文件 ~/.vimrc修改这个文件即可 一个例子 let mapleader ,set number " 显示行号"set relativenumber " 显示相对行号set incsearch " 实时开启搜索高亮set hlsearch " 搜索结果高亮set autoinden…...
Dash框架深度解析:数据驱动型Web应用的Python化革命
一、Dash的定位与技术基因 Dash作为Python生态中的现象级框架,重新定义了数据科学家与Web应用开发之间的边界。它以**“零前端”**为核心设计理念,将React的组件化思想、Plotly的可视化能力与Flask的轻量化服务完美融合,使得Python开发者无需深入JavaScript技术栈即可构建交…...

Linux——线程(1)线程概念与控制
线程?这个名字我们似乎有些眼熟?没错,我们之前提到过的进程和这个有点像。但进程和线程有什么关系呢?本系列我们讲从线程的概念出发,了解一下Linux中的线程以及线程和进程的关系等内容。 一、线程的概念 线程是一个执…...
Redis LFU 策略参数配置指南
一、基础配置步骤 设置内存上限 在 redis.conf 配置文件中添加以下指令,限制 Redis 最大内存使用量(例如设置为 4GB): maxmemory 4gb选择 LFU 淘汰策略 根据键的作用域选择策略: # 所有键参与淘汰 maxmemory-…...

备忘录模式:实现对象状态撤销与恢复的设计模式
备忘录模式:实现对象状态撤销与恢复的设计模式 一、模式核心:在不破坏封装性的前提下保存和恢复对象状态 在软件开发中,经常需要实现 “撤销” 功能(如文本编辑器的撤销修改、游戏存档读取)。直接暴露对象内部状态会…...
蓝桥杯 5. 交换瓶子
交换瓶子 原题目链接 题目描述 有 N 个瓶子,编号为 1 ~ N,放在架子上。 例如有 5 个瓶子,当前排列为: 2 1 3 5 4每次可以拿起 2 个瓶子,交换它们的位置。 要求通过若干次交换,使得瓶子的编号从小到大…...
本地使用Ollama部署DeepSeek
以下是在本地使用Ollama部署DeepSeek的详细教程,涵盖安装、修改安装目录、安装大模型以及删除大模型的操作步骤。 安装Ollama 1. 系统要求 确保你的系统满足以下条件: 操作系统:macOS、Linux或者Windows。足够的磁盘空间和内存。 2. 安装…...

freecad参数化三维模型装配体解析至web端,切换参数组或修改参数
用免费开源的freecad制作全参数化的三维模型,并且装配,上传至服务器,解析至web端,用户可以切换参数或修改参数,驱动模型改变。 freecad全参数化装配体模型解析至web端进行参数切换、修改完整展示_哔哩哔哩_bilibili …...
前端基础之《Vue(9)—混入》
一、什么是混入 1、是一种代码复用的技巧 Vue组件是由若干选项组成的,向组件中混入可复用的选项。 2、作用 比如我封装两个组件,一个是A组件,一个是B组件,发现它里面有相同的选项,就可以用混用的方式来复用它。 二、…...
ORACLE DATAGUARD遇到GAP增量恢复方式修复RAC环境备机的实践
ORACLE DATAGUARD技术是一个常用的数据保护机制,在DATAGUARD运行过程中,遇到异常导致备机不同步,而主库的归档日志也被清理,此时出现GAP,无法同步;就需要人工处理;对于小型数据库重新全量同步数…...
机器人进阶---视觉算法(六)傅里叶变换在图像处理中怎么用
傅里叶变换在图像处理中怎么用 傅里叶变换的基本原理应用场景Python代码示例逐行解释总结傅里叶变换在图像处理中是一种重要的工具,它将图像从空间域转换到频域,从而可以对图像的频率特性进行分析和处理。傅里叶变换在图像滤波、图像增强、图像压缩和图像分析等方面都有广泛应…...
Java知识日常巩固(五)
Java中wait()和 sleep()的区别? 在Java中,wait()和sleep()方法用于线程控制,但它们之间存在几个关键区别: 1. 用途 wait():用于线程间的协作。当一个线程需要等待某个条件满足时,它会调用wait()方法释放锁并进入等待状态,直到其他线程调用相同对象的notify()或notifyAl…...

浅析锁的应用与场景
锁的应用与场景:从单机到分布式 摘要:在多线程和分布式系统中,“锁”是避免资源竞争、保障数据一致性的核心机制。但你真的了解锁吗?什么时候该用锁?用哪种锁?本文通过通俗的比喻和代码示例,带…...

语音合成之五语音合成中的“一对多”问题主流模型解决方案分析
语音合成中的“一对多”问题主流模型解决方案分析 引言“一对多”指的是什么?优秀开源模型的方法CosyvoiceSparkTTSLlaSA TTSVITS 引言 TTS系统旨在模仿人类的自然语音,但其核心面临着一个固有的挑战,即“一对多”问题 。这意味着对于给定的…...

ElementUi的Dropdown下拉菜单的详细介绍及使用
Dropdown是 ElementUI 中用于创建下拉菜单项的一个组件,通常el-dropdown-item 包裹在 el-dropdown 组件中使用。以下从功能特性(一些属性及方法)、使用和高级功能(高亮显示,滚动,额外传参数)三个方面进行详细介绍。 一、功能特性 1.触发方式…...

Linux麒麟 V10 系统找回 root 密码的步骤
Linux麒麟 V10 系统找回 root 密码的步骤 1 环境介绍2 操作步骤2.1重启系统并进入 GRUB 菜单2.2 输入 GRUB 账户密码2.3 修改启动参数2.4 启动系统2.5 修改root 密码2.6 重启系统 3 Linux命令全方位指南实战教程Linux命令学习使用列表 1 环境介绍 有时候root 密码忘记…...
20、 DeepSeekMoE论文笔记
DeepSeekMoE 1、**研究背景与动机**2、传统MoE一、MoE架构核心原理详解1. **标准Transformer块的结构**2. **MoE层对FFN的替代**3. **稀疏性与计算效率** 二、举例说明:以 N 4 N4 N4 专家、 K 2 K2 K2 为例1. **场景设定**2. **亲和度计算与专家选择**3. **输出计…...
在 Spring Boot 中实现 WebSockets
什么是 WebSockets? WebSockets 是一种基于 TCP 的全双工通信协议,允许客户端和服务器之间建立持久的双向连接,用于实时数据交换。相较于传统的 HTTP 请求-响应模型,WebSockets 提供了低延迟、高效率的通信方式,特别适…...

stone 3d v3.3.0版本发布,含时间线和连接器等新功能
1.新加了时间线(timeline)编辑器,可以类似blender一样给对象制作动画 2.新加了度量(metrics)系统,通过scene对象检测器中的useMetrics属性来启用或禁用,启用时所选物体将显示三维度量数据 新加了…...

.whl文件
本文主要介绍了.whl文件的定义,怎么安装.whl文件(离线,在线)。 怎么查看cuda的版本,以及如何安装相应版本的cuda(本地电脑,超算上) 以及如何创建.whl文件 .whl文件的定义 Document…...

Git命令行中vim的操作
Git命令行用vim打开文件,或者用其他git命令打开了文件,需要编辑和保存文件等,有些命令表情奇怪,往往容易忘记这些命令。记录下。 下面这篇比较实用和简练: gitvim编辑文件命令 • Worktile社区https://worktile.com/…...

C#初级知识总结
一、什么是CIL 1.CIL(Common Intermidate Language)是指.Net的公共中间语言,它是一种编程语言。 .Net框架的各种语言在编译时都会编译成同一种中间语言(CIL),之后程序运行的时候CIL会被JIT(Just In Time)转换为二进制语言…...
使用 AI Agent 改善师生互动的设计文档
使用 AI Agent 改善师生互动的设计文档 一、引言 1.1 研究背景 当前教育领域的师生互动存在诸多挑战,如教师负担过重、学生个体差异大导致难以满足所有人的需求,以及信息传递延迟等问题。引入AI-Agent能够有效缓解这些问题,通过自动化手段协…...