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

DAY32 Linux Thread Programming

Linux Thread Programming

I. Core Theoretical Foundations of Threads

1. What is a Thread?

  • Definition: A thread is an execution unit within a process, also referred to as a “Lightweight Process (LWP)”. It belongs to a specific process and shares the process’s resources (code segment, data segment, file descriptors, etc.).
  • Core Purpose: Enable concurrent execution by splitting time-consuming tasks into multiple threads for parallel processing, thereby improving program efficiency (e.g., video rendering, concurrent network requests).

2. Core Characteristics of Threads

CharacteristicExplanation
Resource AllocationProcesses are the system’s smallest unit of resource allocation; threads do not have independent resources (share process resources).
Execution UnitThreads are the system’s smallest unit of execution and the basic object of CPU scheduling.
Hierarchical RelationshipThreads within a process are peer-to-peer; a “main thread” (the thread where themainfunction runs) exists by default.
Resource SharingThreads share the process’s global variables, static variables, file descriptors, etc.; only the stack area (8MB) is independent.
StabilityThreads are unstable: a single thread crash will cause the entire process to exit; processes are relatively stable and isolated from each other.
Creation OverheadThread creation only requires allocating an independent stack area (8MB), while process creation requires allocating a 3GB virtual address space (much higher overhead).
Concurrency EfficiencyThreads have higher concurrency than processes; switching between threads within the same process does not require address space switching, resulting in higher efficiency.

3. Core Differences Between Threads and Processes

Comparison DimensionThreadProcess
Resource AllocationShares resources of the parent process; no independent address space.Has an independent address space and independent resources (code segment, data segment, etc.).
Creation/Switching OverheadLow (only stack area allocation).High (full address space allocation).
Communication MethodDirectly access shared variables; simple communication.Requires IPC (pipes, message queues, etc.); complex communication.
StabilityLow (thread crash leads to process exit).High (processes are isolated from each other).
Concurrency EfficiencyHigh (thread switching without address space switching).Low (high process switching overhead).

4. Core Workflow of Thread Programming (POSIX Standard)

  1. Create Multiple Threads: Usepthread_createto create child threads and specify the thread execution function.
  2. Thread Task Execution: Child threads complete specific tasks (resource operations, computations, etc.) in the callback function.
  3. Thread Resource Recycling: Release thread resources usingpthread_join(blocking recycling) orpthread_detach(automatic recycling) to avoid memory leaks.

5. Detailed Explanation of Key Thread Functions

The POSIX thread library (libpthread) provides core interfaces for thread operations. Below are explanations of commonly used functions:

Function PrototypeFunction Description
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)Creates a child thread.
-thread: Output parameter to store the new thread ID.
-attr: Thread attributes (useNULLfor default).
-start_routine: Thread callback function (execution entry).
-arg: Parameter for the callback function.
- Return value:0on success; error code on failure.
pthread_t pthread_self(void)Gets the current thread ID.
- Return value: ID of the current thread (typeunsigned long, use%lufor printing).
void pthread_exit(void *retval)Child thread exits actively.
-retval: Exit status of the thread (returned to the main thread).
int pthread_cancel(pthread_t thread)Main thread cancels a specified child thread.
-thread: Target thread ID.
- Return value:0on success; error code on failure.
int pthread_join(pthread_t thread, void **retval)Blocks to recycle child thread resources.
-thread: ID of the thread to recycle.
-retval: Receives the exit status of the child thread.
- Return value:0on success; error code on failure.
int pthread_detach(pthread_t thread)Sets the thread detach attribute (resources are automatically recycled after exit).
- No need for the main thread to callpthread_join.

6. Thread Viewing Commands

# View all threads in the system (PID: Process ID, LWP: Thread ID, COMM: Thread name)ps-eLo pid,ppid,lwp,stat,comm# View detailed thread information (including CPU usage, memory, etc.)ps-eLf

II. Practical Code Analysis (8 Core Examples)

The following 8 practical code examples, from basic to advanced, will help you gradually master thread programming skills (all code must be compiled with thepthreadlibrary:gcc filename.c -o filename -lpthread).

Example 01: Create Multiple Threads (01pthread.c)

Function: Create 2 child threads to execute different tasks (sending videos, receiving controls)
#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>#include<string.h>// Thread 1 callback function: Send videovoid*thread_function(void*arg){while(1){printf("Sending video...\n");sleep(1);// Execute every 1 second}returnNULL;}// Thread 2 callback function: Receive controlvoid*thread_function2(void*arg){while(1){printf("Receiving control...\n");sleep(1);}returnNULL;}intmain(){pthread_tthread_id;// Thread 1 IDpthread_tthread_id2;// Thread 2 ID// Create thread 1pthread_create(&thread_id,NULL,thread_function,NULL);// Create thread 2pthread_create(&thread_id2,NULL,thread_function2,NULL);// Main thread blocks (prevents main thread exit from terminating child threads)while(1){sleep(1);}return0;}
Key Notes:
  1. pthread_createparameters: Thread ID pointer, default attributes (NULL), callback function, callback function parameter (NULL).
  2. The main thread must remain running (while(1)); otherwise, the entire process terminates after the main thread exits, and child threads are destroyed.
  3. Compilation command:gcc 01pthread.c -o 01pthread -lpthread.
  4. Running result: The two child threads alternately output “Sending video…” and “Receiving control…”, achieving concurrent execution.

Example 02: Get Thread ID (02pthread_self.c)

Function: Get the IDs of the main thread and child threads usingpthread_self()
#include<stdio.h>#include<pthread.h>#include<unistd.h>#include<stdlib.h>#include<string.h>void*th1(void*arg){while(1){// Print child thread 1 ID (%lu corresponds to unsigned long type)printf("Sending video...tid:%lu\n",pthread_self());sleep(1);}returnNULL;}void*th2(void*arg){while(1){printf("Receiving control...tid:%lu\n",pthread_self());sleep(1);}returnNULL;}intmain(){pthread_ttid1,tid2;pthread_create(&tid1,NULL,th1,NULL);pthread_create(&tid2,NULL,th2,NULL);// Print main thread IDwhile(1){printf("main tid:%lu\n",pthread_self());sleep(1);}return0;}
Key Notes:
  1. pthread_self()has no parameters and returns the ID of the current thread (typepthread_t, recommended to use%lufor formatted output).
  2. Running result: The main thread and two child threads output their respective IDs. You can verify the existence of threads usingps -eLo lwp,comm.

Example 03: Thread Exit (03pthread_exit.c)

Function: The child thread exits actively usingpthread_exit(), and the main thread exits after running a specified number of times
#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>#include<string.h>void*th(void*arg){while(1){printf("sub_th %lu\n",pthread_self());sleep(1);}pthread_exit(NULL);// Child thread exits actively (unreachable here due to while(1), for demonstration only)}intmain(){pthread_ttid;pthread_create(&tid,NULL,th,NULL);inti=8;// Main thread exits after running for 8 secondswhile(i--){printf("main_th %lu\n",pthread_self());sleep(1);}return0;}
Key Notes:
  1. pthread_exit(NULL): The child thread exits actively, with the parameter being the exit status (NULLmeans no return value).
  2. Note: After the main thread exits, child threads are forcibly terminated (even if the child thread haswhile(1)).
  3. Running result: The main thread outputs 8 times and exits, and the child thread terminates simultaneously.

Example 04: Cancel Thread (04phread_cancel.c)

Function: The main thread cancels a child thread usingpthread_cancel()
#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<unistd.h>#include<string.h>void*thread_func(void*arg){while(1){printf("subth %lu\n",pthread_self());sleep(1);}}intmain(){pthread_ttid;pthread_create(&tid,NULL,thread_func,NULL);inti=0;while(1){printf("main th %lu\n",pthread_self());sleep(1);i++;if(i==2){// Cancel the child thread after running for 2 secondspthread_cancel(tid);printf("Child thread canceled\n");}}return0;}
Key Notes:
  1. pthread_cancel(tid): Sends a cancellation request to the specified child thread, which responds at a “cancellation point” (e.g., system calls likesleeporprintf).
  2. Running result: The child thread outputs twice and is canceled, while the main thread continues running.
  3. Note:pthread_cancelonly sends a request. If the child thread has no cancellation points (e.g., a pure computation loop), you need to manually callpthread_testcancel()to set a cancellation point.

Example 05: Thread Resource Recycling (05pthread_jion.c)

Function: The main thread blocks to wait for the child thread to complete and recycles resources usingpthread_join()
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<pthread.h>void*th(void*arg){inti=5;while(i--){printf("workth,%lu\n",pthread_self());sleep(1);}returnNULL;}intmain(intargc,char**argv){pthread_ttid;pthread_create(&tid,NULL,th,NULL);// Block to wait for the child thread tid to complete and recycle its resourcespthread_join(tid,NULL);printf("Child thread finished, main thread exiting\n");return0;}
Key Notes:
  1. pthread_join(tid, NULL): The main thread blocks until the child threadtidexits, preventing the child thread from becoming a “zombie thread” (unrecycled resources).
  2. The second parameter isNULL, indicating no interest in the child thread’s exit status.
  3. Running result: The child thread outputs 5 times and exits, and the main thread prints a message and exits.

Example 06: Get Thread Return Value (06pthread_jionret.c)

Function: The child thread dynamically allocates memory and returns data; the main thread gets the return value and frees the memory usingpthread_join()
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<pthread.h>#include<unistd.h>void*th(void*arg){// Dynamically allocate memory (stack data of the child thread cannot be returned, as it is released when the thread exits)char*str=(char*)malloc(20);strcpy(str,"I'm exiting");returnstr;// Return the dynamically allocated memory address}intmain(intargc,char*argv[]){pthread_ttid;pthread_create(&tid,NULL,th,NULL);void*ret=NULL;// Recycle the child thread and get the return value (ret points to the memory allocated by the child thread)pthread_join(tid,&ret);printf("Child thread return value: %s\n",(char*)ret);free(ret);// Free the memory allocated by the child thread to avoid memory leaksreturn0;}
Key Notes:
  1. The child thread’s return value cannot be a stack variable (the stack is released when the thread exits); usemallocfor dynamic memory allocation.
  2. The main thread receives the return value through the second parameter&retofpthread_joinand must manuallyfreeit after use.
  3. Running result: The main thread prints the string “I’m exiting” returned by the child thread.

Example 07: Pass Struct Parameters (07.c)

Function: The main thread passes struct parameters to the child thread; the child thread prints and returns the struct address
#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>#include<string.h>// Define a struct (store user information)typedefstruct{charname[20];intage;charaddress[50];}PER;void*th(void*arg){// Convert void* type to struct pointerPER*p=(PER*)arg;printf("Information received by child thread:\n");printf("name:%s\n",p->name);printf("age:%d\n",p->age);printf("address:%s\n",p->address);returnp;// Return the struct address}intmain(intargc,char*argv[]){PER p={0};printf("Input name: ");fgets(p.name,sizeof(p.name),stdin);p.name[strlen(p.name)-1]='\0';// Remove the newline charactercharbuf[20]={0};printf("Input age: ");fgets(buf,sizeof(buf),stdin);p.age=atoi(buf);// Convert string to integer and assign to p.ageprintf("Input address: ");fgets(p.address,sizeof(p.address),stdin);p.address[strlen(p.address)-1]='\0';// Remove the newline characterpthread_ttid;// Pass the struct address to the child threadpthread_create(&tid,NULL,th,&p);void*ret=NULL;pthread_join(tid,&ret);printf("Returned struct address: %p\n",ret);// Verify the returned dataprintf("Verified age: %d\n",((PER*)ret)->age);return0;}
Key Notes:
  1. To pass multiple parameters to a thread, encapsulate them in a struct and pass the struct address (avoids type conversion issues with multiple parameters).
  2. The struct is allocated in the main thread’s stack; ensure the main thread does not exit before the child thread finishes using the struct (otherwise, the stack is released, leading to wild pointers).
  3. Running result: The child thread prints the user information passed by the main thread, and the main thread verifies the returned struct data.

Example 08: Thread Resource Sharing (08.c)

Function: Demonstrate resource sharing between threads (modify global variables)
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<pthread.h>inta=20;// Global variable (shared by all threads)void*thread(void*arg){a+=10;// Child thread modifies the global variableprintf("Child thread: a = %d\n",a);returnNULL;}intmain(){pthread_ttid;pthread_create(&tid,NULL,thread,NULL);// Wait for the child thread to complete to ensure the modification takes effectpthread_join(tid,NULL);printf("Main thread: a = %d\n",a);// Main thread reads the modified global variablereturn0;}
Key Notes:
  1. Threads share global variables and static variables; modifications to global variables by child threads are visible to the main thread.
  2. If multiple threads modify shared resources simultaneously, synchronization mechanisms (e.g., mutexespthread_mutex_t) are required to avoid race conditions.
  3. Running result: The child thread outputsa = 30, and the main thread also outputsa = 30, confirming resource sharing.

III. Summary of Key Points

  1. Thread Creation: Usepthread_createto create threads, specifying the callback function and parameters; remember to link thepthreadlibrary during compilation (-lpthread).
  2. Thread ID: Usepthread_self()to get the current thread ID, formatted with%lu.
  3. Thread Exit: Child threads can exit actively withpthread_exit()(returning status) or be canceled by the main thread withpthread_cancel().
  4. Resource Recycling: Usepthread_join()for blocking recycling (to get the return value) orpthread_detach()for automatic recycling (to avoid memory leaks).
  5. Resource Sharing: Threads share global variables and static variables, but independent stack areas require dynamic memory allocation for cross-thread data transfer.
  6. Common Pitfalls:
    • Forgetting to link thepthreadlibrary during compilation (leading to undefined reference errors).
    • Returning stack variables from child threads (stack release causes wild pointers).
    • Not recycling thread resources (leading to zombie threads and memory leaks).
    • Race conditions when multiple threads modify shared resources (needing synchronization mechanisms).

By mastering the theoretical knowledge and practical skills in this article, you can efficiently implement concurrent programming in Linux using POSIX threads. For complex scenarios (e.g., thread synchronization, deadlock prevention), further study of mutexes, condition variables, and other advanced technologies is recommended.

http://www.cnnetsun.cn/news/89750.html

相关文章:

  • 告别 “自动化孤岛”,解锁实验室真正智能
  • Dify版本历史管理的秘密武器:实现安全、可控、可追溯的回滚体系
  • 13.长视频和短视频的目标追踪(yolo_insightface模型)
  • 前端开发必备:JavaScript 核心事件详解与实战
  • 为什么你的服务总崩溃?:Docker MCP 网关负载均衡未正确配置的3大隐患
  • 专利检索漏查1个参数,千万研发卡壳量产线
  • 自动化测试团队效率提升指南
  • LobeChat能否通过等保测评?国内合规性达标
  • paperzz 降重 / 降 AIGC:从重复率超标到学术合规,高校生论文 “隐形风险” 的解决逻辑
  • paperzz AI 期刊论文功能实测:从 “标题输入” 到 “期刊适配提纲”,学术写作如何少走格式与逻辑的弯路?
  • Linux系统安装nginx
  • Dify Docker部署与模型集成指南
  • @所有科技企业:点击链接直达CES Asia2026奖项申报页,错过免费期成本增加3倍
  • Agent概况
  • 13. 搜索引擎-ES-自动补全
  • 36、基础Web服务器与邮件服务配置指南
  • 永磁同步电机三闭环控制Simulink仿真 电流内环 转速 位置外环 参数已经调好 原理与双闭...
  • ISIS路由的基本配置
  • Unloop:为ADHD与神经多样性人群打造的可视化模式映射工具 | ProductHunt 今日热榜 - 12月16日
  • LED显示屏视频会议价格
  • Kamailio 怎样使用 STIR/SHAKEN
  • COMSOL光学仿真:光镊与光力模型专题解析(三个模型详解、近似算法与张量算法探讨)
  • 北斗导航系统在实际应用中总会遇到各种干扰,尤其是脉冲干扰和窄带干扰特别烦人。今天咱们用Matlab仿真几种典型抗干扰方法,顺便看看代码咋写
  • Qwen3-8B大模型快速部署与实战体验
  • AI 时代,数据湖的“拐点”与展望
  • 使用 TensorRT-LLM 高性能部署大语言模型
  • A/B测试在功能验证中的应用:从理论到实践
  • 创建一个rust写的python库[signatures和错误处理]
  • 震撼!这家全景效果企业如何颠覆传统,让客户体验飙升!
  • JVM性能分析