### Linux多线程编程知识点详解 #### 一、线程的概念 线程是现代操作系统中的基本执行单元之一,是进程内的一个执行流程。一个进程至少包含一个线程,即主线程。线程作为CPU调度的基本单位,具有轻量级的特点,它们共享同一个进程的资源,如内存空间、文件句柄等,但每个线程有自己的栈空间和寄存器状态。 #### 二、多线程的优点 - **资源利用率高**:多线程可以使程序同时执行多个任务,提高CPU和其他资源的利用率。 - **响应性好**:在GUI应用中,多线程可以确保用户界面即使在后台任务繁忙时仍然保持响应。 - **结构清晰**:将复杂问题分解成多个独立或协作的小任务,每个任务由一个或多个线程处理,使程序结构更加清晰。 #### 三、何时使用多线程 多线程适用于以下几种情况: - **并发执行的任务**:当程序中有多个可以并行执行的任务时,使用多线程可以让这些任务同时运行,从而加速程序的执行。 - **IO密集型任务**:例如读写文件、网络通信等操作,这些操作往往耗时较长,可以通过多线程实现边读写边处理,提高效率。 - **CPU密集型任务**:对于需要大量计算的任务,如果有多核处理器,使用多线程可以充分利用多个核心的计算能力。 #### 四、线程创建与管理 在Linux下,线程通过`pthread_create`函数来创建。该函数定义如下: ```c int pthread_create(pthread_t *__restrict__ newthread, __const pthread_attr_t *__restrict__ attr, void *(*__start_routine)(void *), void *__restrict__ arg); ``` - `newthread`:指向新线程的标识符。 - `attr`:指定线程属性。如果不需要特别设置,则可以传入`NULL`使用默认属性。 - `__start_routine`:新线程将要执行的函数。 - `arg`:传递给新线程函数的参数。 函数成功返回0,失败则返回错误代码,可通过`strerror(errno)`获取错误信息。 #### 五、线程的终止 线程可以通过以下三种方式结束: 1. **线程执行完毕**:线程执行完其函数后自动退出。 2. **线程取消**:可以通过调用`pthread_cancel()`函数取消一个线程。 3. **显式退出**:通过调用`pthread_exit()`函数退出线程。 #### 六、线程间的同步 在多线程编程中,为了避免多个线程访问同一资源时产生冲突,通常需要进行同步操作。常见的同步机制包括互斥锁(mutex)、条件变量(condition variables)、读写锁(read-write locks)等。 #### 七、示例分析 考虑一个简单的例子,创建两个线程,一个线程对全局变量`num`执行加1操作500次,另一个线程执行减1操作500次。示例代码如下: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <string.h> int num = 0; void* add(void* arg) { int i = 0, tmp; for (; i < 500; i++) { tmp = num + 1; num = tmp; printf("add+1,result is:%d\n", num); } return ((void*)0); } void* sub(void* arg) { int i = 0, tmp; for (; i < 500; i++) { tmp = num - 1; num = tmp; printf("sub-1,result is:%d\n", num); } return ((void*)0); } int main(int argc, char** argv) { pthread_t tid1, tid2; int err; void* tret; err = pthread_create(&tid1, NULL, add, NULL); if (err != 0) { printf("pthread_create error:%s\n", strerror(err)); exit(-1); } err = pthread_create(&tid2, NULL, sub, NULL); if (err != 0) { printf("pthread_create error:%s\n", strerror(err)); exit(-1); } err = pthread_join(tid1, &tret); if (err != 0) { printf("cannot join with thread1:%s\n", strerror(err)); exit(-1); } printf("thread1 exit code%d\n", (int)tret); err = pthread_join(tid2, &tret); if (err != 0) { printf("cannot join with thread2:%s\n", strerror(err)); exit(-1); } printf("thread2 exit code%d\n", (int)tret); return 0; } ``` #### 八、编译问题及解决方案 - **编译错误**: 使用`g++`编译时可能会遇到`undefined reference to 'pthread_create'`错误。 - **解决方案**: 在编译命令中加入`-lpthread`选项,指示链接器链接`pthread`库。 #### 九、示例中的问题解析 在这个示例中,虽然最终结果似乎是正确的,即`num`的值为0,但实际上存在竞争条件的问题。这是因为两个线程都在修改同一个变量`num`,没有采取适当的同步措施。因此,在实际运行过程中,`add`和`sub`线程可能交错执行,导致`num`的值并不总是加500再减500的结果。为了避免这种情况,可以使用互斥锁等同步机制来保护对共享变量的操作。
- 粉丝: 4
- 资源: 901
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 自动多智能体协作生成框架 AutoAgents 的构建与应用研究
- OpenCV计算机视觉项目实战 - 疲劳检测源码(基于Python + OpenCV)
- 有关 Redis 服务器信息的网页显示.zip
- 灭火器检测4-YOLO(v5至v9)数据集合集.rar
- 最快的基于thunk,promise的redis客户端,支持所有redis功能 .zip
- 更快地缓存 Wordpress.zip
- 版本控制系统中Git的安装与配置指南
- Building Resilient Architectures on AWS.pdf
- 扫描 Redis RDB 以查找大键 分析redis的RDB文件,输出big key报告.zip
- 我使用 redis 的工具.zip