linux 线程

线程的概念

一、线程的定义

线程是进程中的⼀个执行单元,负责当前进程中程序的执行,⼀个进程中至少有⼀个线程
⼀个进程中是可以有多个线程
多个线程共享同一个进程的资源,每个线程参与操作系统的统一调度
可以简单理解: 进程 = 进程资源 + 主线程 + 子线程 +......

二、线程与进程

线程与进程区别
内存空间
一个进程中多个线程共享同一个内存空间
多个进程拥有独立的内存空间
进程 / 线程间通讯
线程间通讯方式简单
进程间通讯方式复杂
并发操作,线程比进程更节约资源
总结:
联系紧密的任务在并发时优先选择多线程,如果任务之间比较独立,在并发时建议选择多进程。

三、线程资源

共享进程的资源
同一块地址空间
文件描述符表
每种信号的处理方式(如: SIG_DFL,SIG_IGN 或者自定义的信号优先级)
当前工作目录
用户 id 和组 id
独立的资源
线程栈
每个线程都有私有的上下文信息。
线程 ID
寄存器的值
errno 变量
信号屏蔽字以及调度优先级

线程相关的命令

Linux 系统有很多命令可以查看进程,例如 pidstat top ps ,也可以查看一个进程下的线程

一、pidstat

ubuntu 下安装 sysstat 工具后,可以支持 pidstat
sudo apt install sysstat
选项
-t: 显示指定进程所关联的线程
-p: 指定进程 pid
示例:使用 pidstat 命令查看某一个进程下的线程
step 1 : 运行 sem 程序 , 此程序包含两个进程
step 2 : 查看 sem 进程所对应的 id
step 3 : 使用 pidstat 命令查看相应进程的线程

二、top 命令

top 命令查看某一个进程下的线程,需要用到 -H 选项在结合 -p 指定 pid
示例:使用 top 命令查看某一个进程下的线程
sudo apt install sysstat
选项
-t: 显示指定进程所关联的线程
-p: 指定进程 pid
top -H -p 3027

三、ps命令

ps 命令结合 -T 选项就可以查看某个进程下所有线程

创建线程

一、线程创建

创建线程调用 pthread_create 函数
函数头文件
#include <pthread.h>
函数原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *
(*start_routine) (void *), void *arg);
函数功能
创建一个子线程
函数参数
thread:线程ID变量指针
attr:线程属性,默认属性可设置为NULL
start_routine:线程执行函数
arg:线程执行函数的参数
函数返回值
成功:返回 0
失败:返回 错误码
Tips
typedef unsigned long int pthread_t;
一旦子线程创建成功,则会被独立调度执行,并且与其他线程 并发执行
在编译时需要链接 -lpthread [Compile and link with -pthread]
示例:创建一个线程,打印线程 ID
问题:
1. 在编译时出现下面的错误
implicit declaration of function 'pthread_create'
解决办法: pthread 库不是 Linux 系统默认的库,编译的时候需要加上库 -lpthread
2. 程序执行的结果中只打印了 tid, 子线程没有执行
原因是 子线程还没有来得及执行,主线程已经结束,导致其他子线程都必须结束
解决办法: 保证主线程不先于子线程结束 23 章节详解)

线程的等待、退出和分离

一、线程退出

线程退出使用 pthread_exit 函数
函数头文件
#include <pthread.h>
函数原型
void pthread_exit(void *retval);
函数功能
让线程退出,并返回值
函数参数
retval:线程返回值,通过指针传递
函数返回值
成功:返回 0
失败:返回 -1
Tips:
1. 当主线程调用 pthread_exit 函数时,进程不会结束,也不会导致其他子线程退出
2. 任何线程调用 exit 函数会让进程结束

二、线程等待

主线程需要等待子线程退出,并释放子线程资源
线程等待调用 pthread_join 函数,会阻塞调用线程
函数头文件
#include <pthread.h>
函数原型
int pthread_join(pthread_t thread, void **retval);
函数功能
等待子线程退出,并释放子线程资源
函数参数
thread:线程 ID
retval:获取线程退出值的指针
函数返回值
成功:返回0
失败:返回错误码
例代码:创建一个子线程,主线程等待子线程退出
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
// 线程执行函数
void* do_thread_function(void* args)
{
    printf("do thread ....\n");
    pthread_exit(NULL);
}
int main()
{
    pthread_t thread_id;
    int result =pthread_create(&thread_id,NULL,do_thread_function,NULL);
    if(result!=0)
    {
        fprintf(stderr,"pthread error:%s\n",strerror(result));
        exit(EXIT_FAILURE);
    }
    printf("thread id is %ld\n",thread_id);
    pthread_join(thread_id,NULL);
    return 0;
}

三、线程分离

线程分为可结合的与可分离的
可结合
可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源
(如栈)是不释放的。
线程创建的默认状态为可结合的,可以由其他线程调用 pthread_join 函数等待子线程退出并
释放相关资源
可分离
不能被其他线程回收或者杀死的, 该线程的资源在它终止时由系统来释放
线程分离调用 pthread_detach 函数
函数头文件
#include <pthread.h>
函数原型
int pthread_detach(pthread_t thread);
函数功能
设置在线程退出后,由操作系统自动释放该线程的资函数参数
thread:线程ID
函数返回值
成功:返回0
失败:返回-1源
注意: 线程分离函数不会阻塞线程的执行
示例代码:创建一个线程,并设置线程为可分离状态
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
// 线程执行函数
void* do_thread_function(void* args)
{
printf("do thread ....\n");
pthread_exit(NULL);
}
int main()
{
    pthread_t thread_id;
    int result =pthread_create(&thread_id,NULL,do_thread_function,NULL);
    if(result!=0)
    {
        fprintf(stderr,"pthread error:%s\n",strerror(result));
        exit(EXIT_FAILURE);
    }
    printf("thread id is %ld\n",thread_id);
    //线程分离
    pthread_detach(thread_id);
    return 0;
}

补充:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值