线程以及pthread库的使用

https://blog.csdn.net/weixin_38102771/article/details/91351126
https://blog.csdn.net/qq_29677867/article/details/108571388?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242
一.什么是线程
你可以想象你一边听歌一边打游戏,如果是操作系统会怎么做呢?先执行 ListenMusic 再执行 PlayGame,还是先执行 PlayGame 再执行 ListenMusic 呢?好像都不太合适。为了实现这个目的,就需要引入线程这个概念。线程是 CPU 调度的最小执行单位,你可以创建一个线程用于 ListenMusic,再创建一个线程去 PlayGame,这样操作系统就是同时处理这两个任务的(并发)。

二.pthread库
(1) 使用说明
POSIX 标准定义了一套线程操作相关的函数,用于让程序员更加方便地操作管理线程,函数名都是以前缀 pthread_ 开始,使用时要包含 <pthread.h>,而且在链接的时候要手动链接 pthread 这个库,如:gcc main.c -lpthread -o main。

(2) 常用函数

  1. pthread_create
    函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

功能说明:创建一个线程。

参数说明

thread:线程句柄,需要先定义一个 pthread_t 类型变量 thread,将该变量的地址 &thread 传递到该参数中去。这是一个传出参数,传递进去的 thread 会得到系统为我们创建好的线程句柄。

attr:线程属性,通过该参数可以设置创建的线程属性,如果要使用默认属性直接传递 NULL 即可。

start_routine:线程函数,它是一个函数指针类型,返回类型为 void *,参数为一个 void * 类型变量,创建好这样类型的一个函数,将函数名传递进去即可。

arg:线程参数,代表需要在主线程传递给子线程的参数,给 arg 赋值后可以在线程函数的参数中取到。

返回值说明

    成功情况下返回 0,失败情况下返回错误码,并且 tid 的值是不确定的。Linux 环境下所有线程函数调用失败时均是返回错误码,除了部分返回值为 void 的函数。关于错误码的说明在这里的第 8 小节。
  1. pthread_self
    函数原型:pthread_t pthread_self(void);

功能说明:获取线程 ID。

参数说明:无参数。

返回值说明:如果在主线程中调用该函数会返回主线程的线程 ID,如果在子线程中调用该函数会返回子线程的线程 ID,该函数没有失败的情况。

额外说明:线程 ID 是进程内部识别标志,两个进程间线程 ID 允许相同。

  1. pthread_equal
    函数原型:int pthread_equal(pthread_t t1, pthread_t t2);

功能说明:比较两个线程 ID 是否相等,在 Linux 系统中 pthread_t 都设计为 unsigned long 类型,所以可以直接用 == 判别是否相等,但是如果某些系统设计为结构体类型,那么就可以通过 pthread_equal 函数判别是否相等了。

参数说明:要比较的两个线程 ID。

返回值说明:若相等返回非 0 数值,否则返回 0。

  1. pthread_exit
    函数原型:void pthread_exit(void *retval);

功能说明:将单个线程退出。

参数说明:retval 为该线程的返回状态,如果主线程调用 pthread_join 可以获取到该返回状态。

返回值说明:void。

额外说明:如果在主线程中调用了 pthread_exit(NULL),则主线程退出,如果子线程存在会继续执行。如下代码,就算主线程先退出了,也不会影响子线程打印"我是子线程"。注意如果使用 exit 退出会导致整个进程结束。

  1. pthread_join
    函数原型:int pthread_join(pthread_t thread,void **retval);

功能说明:阻塞等待线程退出,获取线程退出状态,相当于进程中的 waitpid 函数,如果线程退出,pthread_join 立刻返回。

参数说明

thread:代表要等待线程的线程 ID

retval:获取该线程的退出状态

返回值说明

    成功情况下返回 0,失败则返回错误码。
  1. pthread_detach
    函数原型:int pthread_detach(pthread_t thread);

功能说明:将线程 ID 为 thread 的线程分离出去,所谓分离出去就是指主线程不需要再通过 pthread_join 等方式等待该线程的结束并回收其线程控制块(TCB)的资源,被分离的线程结束后由操作系统负责其资源的回收。

参数说明:thread 为要分离的线程的线程 ID。

返回值说明

    成功情况下返回 0,失败情况下返回错误码。

额外说明

    一般来说,主线程是要负责创建出来的子线程的资源回收工作的。如果主线程先于子线程退出并且子线程没有设置为分离状态,那么子线程结束后其资源是无法得到回收的,会造成资源浪费和系统臃肿;如果主线程先于子线程退出但是子线程时分离状态,那么子线程退出的时候操作系统会自动回收其资源。
  1. pthread_cancel
    函数原型:int pthread_cancel(pthread_t thread);

功能说明:杀死线程。

参数说明:thread 为要杀死的线程的线程 ID。

返回值说明:成功情况下返回 0,失败情况下返回错误码。

程序说明

    分别创建了两个线程,pthread_func3 是一个死循环。在主线程中 sleep(3) 之后调用 pthread_cancel 结束子线程 pthread_func3,再调用 pthread_join 回收该子线程,由于子线程已经被杀死,此时 pthread_join 返回 -1。

    如果在子线程中的 while(1) 里,将 printf 和 sleep 函数注释掉,会发现杀不死该线程,原因是 pthread_cancel 并不等待线程终止,它仅仅提出了一种请求,需要子线程执行到特定的取消点才能终止该线程(如一些系统调用 write,pause 等地方)。如果线程中没有系统调用的函数,可以加入 pthread_testcancel 函数作为取消点。
  1. 常见错误码
    EDEADLK:检测到线程发生死锁

EINVAL:线程不是可以等待回收的线程(后续会讲到线程分离)或者有其他线程已经准备等待回收该线程了

ESRCH:该线程 ID 不存在

三.使用线程的好处
在 Linux 编程中,多线程编程无疑是十分重要的。它可以提高程序的并发处理能力,线程间通信和共享数据十分方便,而且相对于多进程来说,它更加轻量级、好用。
————————————————
版权声明:本文为CSDN博主「梦别停」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38102771/article/details/91351126

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值