APUE——线程

12 篇文章 0 订阅

1.一个进程中的所有线程都可以访问该进程的组成部件,如文件描述符和内存。线程也包含了表示进程内执行环境必须的信息,包括线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、error变量及线程私有数据。

2.线程ID只在它所属的进程环境中有效,用一个pthread_t型的结构体表示。取当前 TID 的函数是:
#include <pthread.h>
pthread_t pthread_self(void);
对两个 TID 进行比较(不应直接使用逻辑运算符)的函数是:
#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);

3.线程的创建
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t 
*restrict attr, void *(*start_rtn)(void), void *restrict arg);
该函数用于创建一个新的线程,其 TID 放在 tidp   指向的地址,它的属性放在 attr   指向的地址,该线程将函数指针 start_rtn   处(启动例程)开始执行,并引用 arg   指向的向量表作为函数参数。

几个需要注意的地方:
• 函数指针 start_rtn   指向一个指针函数,即启动例程必须返回一个指针。
• 是新线程还是原来的线程先运行事先无法假设;新线程可能在原线程的 pthread_create 返回前就
开始运行;
新的线程共享同一进程的所有地址空间、信号屏蔽字等,但该线程的未决信号集将被清除,这意
味着新线程是不能捕捉创建之前产生的信号的;
prthread 库函数调用失败时通常不修改 errno,而是返回错误代码。

4.终止一个线程的终止有多种方式:
• 线程通过调用 exit、_exit、_Exit等终止整个进程;
• 线程从启动例程返回;
• 线程通过调用 pthread_exit退出;
#include <pthread.h>
void pthread_exit(void *rval_ptr);
其中,指针 rval_ptr   处可以放置退出时要传递的相关信息。其它函数通过 pthread_join访问这个指针:
#include <pthread.h>
int thread_join(pthread_t thread, void **rval_ptr);
该函数以类似 wait的方式阻塞并等待指定的线程 thread 退出,并将其退出时的信息保存到rval_ptr   指向的指针处;若线程从启动例程返回,则退出信息指针为该例程的返回值;若调用了 pthread_exit,则为其参数;若被其它线程取消,则为常数 PTHREAD_CANCELED;要特别注意的是,pthread_exit 的指针参数不能是一个局部变量,否则在线程结束时该段内存会被回收,其它线程 pthread_join 的时候就会出错;

还可以使用 pthread_detach(3)分离线程,此时就不用也不能 join 它的退出状态。
#include <pthread.h>

int pthread_detach(pthread_t tid);

线程被同一进程的其它进程取消;
#include <pthread.h>
int pthread_cancel(pthread_t tid);
该函数用于取消指定的线程,它发出终止请求后就立即返回,并不检查指定的线程是否已经终止;
函数 pthread_cleanup_push 使用类似 atexit(3)的方式注册一个线程终止时的清理函数。

include <pthread.h>
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
可以通过调用 pthread_exit(3), 响应 pthread_cancel(3)的请求,或者调用函数 pthread_cleanup_pop 来隐式或显示的调用已注册的线程清理函数。(但是从启动例程中返回不会调用清理函数)
#include <pthread.h>
void pthread_cleanup_pop(int execute); 
该函数用于显式的解除注册最近一个注册的线程清理函数,即线程清理函数使用类似栈的压(push)、弹(pop)方式进行注册和解除;参数 execute   为 0 时表示仅解除注册,而不执行,非 0 则表示执行该清理函数并解除注册;要特别注意的是,pthread_cleanup_push(3)和 pthread_cleanup_pop(3)可能是通过宏来实现的,必须在同一个缩进级别的代码块中配对使用,即编写代码时不能只调用其中一个,否则编译将通不过。因为它们的宏实现通常使用了单的花括号。

5.线程同步

(1)互斥量

#include<pthread.h>

int  pthread_mutex_init(pthread_mutex_t  *restrict  mutex,  const pthread_mutexattr_t  *restrict attr);

int  pthread_mutex_destroy(pthread_mutex_t *mutex);

分别用来初始化一个互斥锁和销毁一个互斥锁。

int pthread_mutex_lock(pthread_mutex_t  *mutex);

int pthread_mutex_trylock(pthread_mutex_t  *mutex);

int  pthread_mutex_unlock(pthread_mutex_t  *mutex);

第一个用来锁住一个互斥量,如果互斥量已经上锁则调用线程将阻塞到直到互斥量被解锁。第二个函数则是非阻塞版本。第三个函数是解锁函数。

(2)读写锁

在读模式下,可以加读锁,不能加写锁;在写模式下,只能加一个写锁,其他线程不能加写锁或读锁。适用于读次数远大于写次数的场景。

(3)条件变量

由互斥量和条件变量组成,其中条件本身由互斥量保护。线程在改变条件状态之前首先要锁住互斥量。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值