当前位置: 首页 > news >正文

自学嵌入式day32,线程

线程基本概念
  • 线程定义:在 Linux 中,线程属于某个进程,是轻量级的执行单元。每个进程默认有一个主线程,线程间是平级关系。
  • 作用:实现并发执行,提高资源利用率和响应速度。
  • 特征
    • 进程是最小资源分配单位,线程是最小执行单位。
    • 线程共享进程资源(如内存空间),但拥有独立的栈区(通常 8MB)。
    • 稳定性较差:若一个线程崩溃,可能导致整个进程崩溃。
    • 创建开销小:线程创建只需在进程空间中开辟新栈区,而进程创建需分配更多资源(如 3GB 空间)。
    • 并发度高:线程并发优于进程,因为切换成本更低。
线程与进程的区别
  • 资源共享:线程共享进程资源(全局变量、堆等),进程资源独立。
  • 稳定性:进程更稳定(独立地址空间),线程不稳定(共享资源)。
  • 创建开销:线程开销小(仅栈区),进程开销大(完整资源分配)。
  • 并发度:线程并发效率更高,适合高并发场景。
线程编程步骤(POSIX)
  1. 创建线程:使用pthread_create函数。
  2. 线程操作:在线程函数中执行任务。
  3. 资源回收:通过pthread_join或设置分离属性回收资源(避免内存泄漏)。
查看线程信息

在 Linux 终端,可使用以下命令查看线程:

ps -eLf # 显示进程和线程信息 ps -elf # 详细列表
线程相关函数详解

下面逐一解释您列出的函数,并提供代码示例。所有示例基于 C 语言,使用 POSIX 线程库。

  1. 获取线程 ID (pthread_t pthread_self(void))

    • 功能:返回当前线程的 ID(pthread_t类型,通常为unsigned long)。
    • 参数:无。
    • 返回值:成功返回线程 ID,失败返回非零错误码。
    • 示例
      #include <stdio.h> #include <pthread.h> void *thread_func(void *arg) { pthread_t tid = pthread_self(); printf("Thread ID: %lu\n", (unsigned long)tid); pthread_exit(NULL); } int main() { pthread_t tid; pthread_create(&tid, NULL, thread_func, NULL); pthread_join(tid, NULL); return 0; }
  2. 线程退出 (void pthread_exit(void *retval))

    • 功能:线程自行退出,可传递退出状态(如错误码或消息)。
    • 参数retval为退出状态指针(可自定义数据类型)。
    • 返回值:无。
    • 示例
      #include <stdio.h> #include <pthread.h> void *thread_func(void *arg) { printf("Thread exiting...\n"); int *status = malloc(sizeof(int)); *status = 42; // 自定义退出状态 pthread_exit(status); } int main() { pthread_t tid; void *retval; pthread_create(&tid, NULL, thread_func, NULL); pthread_join(tid, &retval); printf("Thread exit status: %d\n", *(int *)retval); free(retval); return 0; }
  3. 请求结束线程 (int pthread_cancel(pthread_t thread))

    • 功能:向指定线程发送取消请求(线程需设置可取消状态)。
    • 参数thread为目标线程 ID。
    • 返回值:成功返回 0,失败返回非零错误码。
    • 示例
      #include <stdio.h> #include <pthread.h> #include <unistd.h> void *thread_func(void *arg) { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); while(1) { printf("Thread running...\n"); sleep(1); } pthread_exit(NULL); } int main() { pthread_t tid; pthread_create(&tid, NULL, thread_func, NULL); sleep(3); // 等待 3 秒后取消线程 pthread_cancel(tid); pthread_join(tid, NULL); printf("Thread canceled.\n"); return 0; }
  4. 线程资源回收 (int pthread_join(pthread_t thread, void **retval))

    • 功能:阻塞等待指定线程结束并回收资源(栈、状态等)。
    • 参数
      • thread:目标线程 ID。
      • retval:接收线程退出状态(需匹配pthread_exit的返回值)。
    • 返回值:成功返回 0,失败返回非零错误码。
    • 示例:见以上pthread_exit示例。
  5. 设置分离属性 (int pthread_detach(pthread_t thread))

    • 功能:设置线程为分离状态,退出后系统自动回收资源(无需pthread_join)。
    • 参数thread为目标线程 ID(通常线程自身调用)。
    • 返回值:成功返回 0,失败返回非零错误码。
    • 示例
      #include <stdio.h> #include <pthread.h> void *thread_func(void *arg) { pthread_detach(pthread_self()); // 设置自身为分离状态 printf("Detached thread running.\n"); pthread_exit(NULL); } int main() { pthread_t tid; pthread_create(&tid, NULL, thread_func, NULL); sleep(1); // 主线程短暂等待 printf("Main thread continues.\n"); return 0; // 分离线程资源由系统回收 }
完整示例:线程创建与回收

以下程序展示创建多个线程、使用共享资源,并回收资源:

#include <stdio.h> #include <pthread.h> #define NUM_THREADS 3 void *worker(void *arg) { int thread_num = *(int *)arg; printf("Thread %d started. ID: %lu\n", thread_num, (unsigned long)pthread_self()); pthread_exit(NULL); } int main() { pthread_t threads[NUM_THREADS]; int thread_args[NUM_THREADS]; // 创建线程 for (int i = 0; i < NUM_THREADS; i++) { thread_args[i] = i; if (pthread_create(&threads[i], NULL, worker, &thread_args[i]) != 0) { perror("pthread_create error"); return 1; } } // 回收线程资源 for (int i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); } printf("All threads completed.\n"); return 0; }
注意事项
  • 资源管理:避免内存泄漏,确保回收线程资源(使用pthread_join或设置分离属性)。
  • 线程安全:共享资源时需用互斥锁(如pthread_mutex)防止竞态条件。
  • 错误处理:检查函数返回值,使用perrorstrerror诊断错!
http://www.cnnetsun.cn/news/92346.html

相关文章:

  • 1小时搭建:VSCode远程开发环境原型
  • 电商项目实战:Vue3父子组件传值最佳实践
  • 【LLM基础教程】从序列切分到上下文窗口01_为什么序列建模必须切分数据
  • 备赛三--
  • 高并发时代的“确定性”挑战——为何稳定性正在成为 JVM 的下一场核心竞争?
  • C语言之最大公约数和最小公倍数问题
  • LobeChat能否对接Telegram Bot?跨平台消息同步实现
  • AI如何用博图加速工业自动化开发
  • C++:二叉搜索树(BST)完全指南(从概念原理、核心操作到底层实现)
  • Splashtop AEM 在 G2冬季报告中斩获“最佳预估 ROI”殊荣
  • 赋能传统硬件:具身智能如何激活工业机器人的二次生命
  • 【模板:求组合数】信息学奥赛一本通 1648:【例 1】「NOIP2011」计算系数 | 1866:【11NOIP提高组】计算系数 | 洛谷 P1313 [NOIP 2011 提高组] 计算系数
  • 金运环球:金价高位回落,非农与零售数据即将来袭
  • 活动力度大的门头招牌企业
  • 【毕业设计】基于JavaWeb的兽医站管理系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • Java毕设选题推荐:基于JavaWeb的兽医站管理系统的设计与实现现代化兽医站管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Arduino配置8266开发板
  • 【课程设计/毕业设计】基于SpringBoot+Vue茶叶销售系统的设计与实现基于Java语言的茶叶销售系统的前端设计与实现【附源码、数据库、万字文档】
  • 41. 缺失的第一个正数
  • 打了一堆板子,才发现是VDD_EXT的锅
  • 技术亲民倒计时!飞猫 RedCap 轻量化 5G 随身 WiFi 即将上市!
  • # 深入 Ascend C 内存模型:掌握UB、GM与流水线优化,打造极致AI算子
  • 冥想第一千七百三十五天(1735)
  • 代理IP和普通IP有什么区别?这篇文章帮你捋明白
  • 体系结构分类和指令系统
  • 基于AI数字人系统源码的低成本开发方案与实践经验
  • SQL 调优全解:从 20 秒到 200 ms 的 6 步实战笔记(附脚本)
  • YOLO目标检测模型如何对接Apipost平台
  • 简单的创建一个Spring Boot网页
  • 鼠标滚轮缩放图片:前端实现高清无损放大技巧(附实战代码)