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

5、linux c 线程 - 上

【四】线程

1. 线程的创建

#include <pthread.h>
​
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*routine)(void *), void *arg);
  • pthread_t *thread:指向线程标识符的指针,用于存储新创建线程的 ID。

  • const pthread_attr_t *attr:线程属性指针,通常传 NULL 使用默认属性。

  • void *(*routine)(void *):线程执行的函数指针,即线程开始执行的函数。

  • void *arg:传递给线程函数的参数,可以是任意类型,但需要正确转换。

返回值

  • 成功:返回 0。

  • 失败:返回非零错误码。

特点

  • 创建线程需要时间,如果主进程很快退出,线程可能无法执行。

  • 主进程退出时,其创建的所有线程也会随之退出。

示例代码

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
​
// 线程执行函数
void *thread_function(void *arg) {
    printf("Thread is running, TID: %lu\n", pthread_self());
    sleep(2);
    printf("Thread finished\n");
    return NULL;
}
​
int main() {
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, thread_function, NULL);
    if (ret != 0) {
        perror("pthread_create failed");
        return 1;
    }
    printf("Main process, PID: %d\n", getpid());
    sleep(3); // 确保线程有时间运行
    return 0;
}

2. 线程的退出

pthread_exit

#include <pthread.h>
​
void pthread_exit(void *retval);
  • void *retval:线程的返回值,可以是任意类型,但需要正确转换。

特点

  • 调用 pthread_exit 可以使线程正常退出。

  • 主进程退出时,其创建的所有线程也会随之退出。

示例代码

#include <stdio.h>
#include <pthread.h>
​
// 线程执行函数
void *thread_function(void *arg) {
    printf("Thread is running, TID: %lu\n", pthread_self());
    sleep(2);
    printf("Thread finished\n");
    pthread_exit((void *)0); // 线程正常退出
    return NULL;
}
​
int main() {
    pthread_t tid;
    pthread_create(&tid, NULL, thread_function, NULL);
    printf("Main process, waiting for thread...\n");
    sleep(3);
    return 0;
}

3. 获取线程 ID

pthread_self

#include <pthread.h>
​
pthread_t pthread_self(void);

特点

  • 返回当前线程的 ID。

  • 可以通过 pthread_create 的第一个参数获取线程 ID,也可以在线程内部调用 pthread_self 获取。

示例代码

#include <stdio.h>
#include <pthread.h>
​
// 线程执行函数
void *thread_function(void *arg) {
    printf("Thread is running, TID: %lu\n", pthread_self());
    return NULL;
}
​
int main() {
    pthread_t tid;
    pthread_create(&tid, NULL, thread_function, NULL);
    printf("Main process, PID: %d\n", getpid());
    sleep(1);
    return 0;
}

4. 线程间参数传递

参数传递方式

pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*routine)(void *), void *arg);
  • 通过地址传递参数:注意类型的转换。

  • 值传递:编译器可能会告警,需要程序员自己保证数据长度正确。

示例代码

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
​
// 线程执行函数
void *thread_function(void *arg) {
    int num = *((int *)arg); // 转换为 int 类型
    printf("Thread is running, received number: %d\n", num);
    free(arg); // 释放分配的内存
    return NULL;
}
​
int main() {
    pthread_t tid;
    int *num = (int *)malloc(sizeof(int));
    *num = 42;
    pthread_create(&tid, NULL, thread_function, (void *)num);
    printf("Main process, sent number: %d\n", *num);
    sleep(1);
    return 0;
}

5. 线程的回收

pthread_join

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);
  • pthread_t thread:要回收的线程 ID。

  • `void retval**:用于存储线程的返回值,可以是NULL`。

返回值

  • 成功:返回 0。

  • 失败:返回非零错误码。

特点

  • pthread_join 是阻塞函数,如果回收的线程未结束,则一直等待。

示例代码

#include <stdio.h>
#include <pthread.h>

// 线程执行函数
void *thread_function(void *arg) {
    printf("Thread is running, TID: %lu\n", pthread_self());
    sleep(2);
    printf("Thread finished\n");
    return (void *)0;
}

int main() {
    pthread_t tid;
    void *retval;
    pthread_create(&tid, NULL, thread_function, NULL);
    printf("Main process, waiting for thread...\n");
    int ret = pthread_join(tid, &retval);
    if (ret != 0) {
        perror("pthread_join failed");
        return 1;
    }
    printf("Thread exited with status: %ld\n", (long)retval);
    return 0;
}

6. 线程的分离

1、使用 pthread_detach

#include <pthread.h>

int pthread_detach(pthread_t thread);

2、创建线程时设置分离属性

#include <pthread.h>

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

特点

  • 分离线程在退出时会自动回收资源,无需显式调用 pthread_join

示例代码

#include <stdio.h>
#include <pthread.h>

// 线程执行函数
void *thread_function(void *arg) {
    printf("Thread is running, TID: %lu\n", pthread_self());
    sleep(2);
    printf("Thread finished\n");
    return NULL;
}

int main() {
    pthread_t tid;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_create(&tid, &attr, thread_function, NULL);
    printf("Main process, PID: %d\n", getpid());
    sleep(3);
    return 0;
}
  1. 查看线程

ps -eLf | grep [名字]

相关文章:

  • 基于STM32的两路电压测量仿真设计Proteus仿真+程序设计+设计报告+讲解视频
  • 使用LVS的 NAT 模式实现 3 台RS的轮询访问
  • (学习总结30)Linux 进程优先级、进程切换和环境变量
  • 使用LLM 构建MCP服务端和客户端
  • 信息安全和病毒防护——防火墙的作用
  • SFT和RLHF是什么意思?
  • Axure项目实战:智慧城市APP(四)医疗信息(动态面板、选中交互应用)
  • Jboss中间件漏洞攻略
  • java学习笔记6
  • 【云馨AI-大模型】大模型的开发和应用中,Python、PyTorch和vLLM关系概括
  • 从扩展黎曼泽塔函数构造物质和时空的结构-1
  • netty框架概述
  • 蓝桥云客 合并数列
  • 01、聊天与语言模型
  • [python]IsaacGym安装
  • 多线程编程
  • Android应用退出后不在任务栏显示
  • 如何做好需求管理培训
  • Rk3588,Opencv读取Gmsl相机,Rga yuv422转换rgb (降低CPU使用率)
  • 2.1.1~2词法分析的手工构造
  • 回家了!子弹库帛书二、三卷将于7月首次面向公众展出
  • 专利申请全球领先!去年我国卫星导航与位置服务产值超5700亿
  • 莫高义在第四届中国新闻发言人论坛开幕式上的致辞
  • “GoFun出行”订单时隔7年扣费后续:平台将退费,双方已和解
  • 夜读丨什么样的前程值得把春天错过
  • 遭车祸罹难的村医遇“身份”难题:镇卫生院否认劳动关系,家属上诉后二审将开庭