从进程到线程
进程:正在运行的程序,是资源分配的基本单位。
任何一个线程 main 里 return
exit
abort
信号
导致整个进程终止,所以线程终止。
子线程终止自己:
从thraedFunc中return(不建议) return null
从任何位置调用pthread_exit(void* retval)
pthread_join(pthread_t thread,void **retval);
join--> 河流合并 类似多进程的wait() , 不同的是 可以等待任何一个线程的终止。
main: 栈中分配void*
join: void** 拷贝子线程的终止状态, 主调函数申请void* 的内存,而join()试图修改主调函数的void* (使用void** 的原因)
t1: --> retval(终止信息)
forK -----> pthread_creat
exit -----> pthread_exit
wair ----->pthread_join() tid 而不是&tid
多线程和信号不能同时使用:多个线程会共享注册信号的信息,用户无法得知是哪个线程递送信号。-->
线程的取消(类似信号)-->pthread_cancel() 给另一个线程发送取消请求(不会马上终止,而是将 取消标志 置为一,“特殊函数”(取消点)调用后终止线程)
取消点--->(操作文件 引发阻塞)的系统调用。 printf() 有一个不是(pthread_mtex_lock())
手动添加取消点:pthread_testcancel() 如果取消标志为真,终止本线程。
cancel的流程:1 cancel会立即修改目标线程的取消标志位
2 目标线程运行到一些特殊函数
3 取消点函数调用完前终止线程 ---> 异步终止,导致资源泄露 --> 运行线程终止清理函数
资源清理栈:申请资源:malloc open opendir semop mutex_lack 释放行为---> free close closedir semop mutex_unlock
申请资源以后,把对应的释放行为压栈,(pthread_cleanup_push())
当线程因为1:pthread_exit 2: 被cancel 终止时,将栈清空。
线程可以主动调用pthread_cleanup_pop()。
pthread_cleanup_push 和 pthread_cleanup_pop 都是宏函数,编译时会代码展开。
资源清理
cleanup 的目的:线程无论在什么时候终止,都会根据申请的资源执行理性的释放行为。
核心数据结构:清理函数栈
①每次申请资源时,把清理操作入栈。
②弹栈的时机 pthread_exit() pthread_cancel() pthread_cleanup_pop() ,不要使用return
③push 和 pop 成对出现。
④有了pop,不要手动回收资源。
mutex 互斥锁
MUTal EXclusion device, 一个线程可以做加锁操作①若有任何线程持有锁,加锁的线程会阻塞 P ②若未加锁,加锁操作,将锁加锁,线程继续运行 V