Linux多线程编程API笔记,梳理查阅

本文详细介绍了Linux下多线程编程的API,包括线程创建、终止、线程ID、线程连接与分离、互斥量和条件变量等,并讲解了线程同步和取消的相关知识。
摘要由CSDN通过智能技术生成

简述多线程

  • 线程是允许应用程序并发执行多个任务的一种机制

Pthread数据类型

数据类型描述
phtread_t线程ID
pthread_mutex_t互斥对象
pthread_mutexattr_t互斥属性对象
pthread_cond_t条件变量
pthread_condattr_t条件变量的属性对象
pthread_key_t线程特有数据的键
pthread_once_t一次性初始化控制上下文
pthread_attr_t线程的属性对象

Pthreads函数返回值

  • 从系统调用和库函数中返回状态,传统的做法是:返回0表示成功,返回-1表示失败,并设置errno值以标识错误原因,
  • Pthread则:返回0表示成功,返回任意正值表示失败,这一失败的返回值与errno中值的含义相同。

线程相关API

创建线程
#include <pthread.h>
int pthread_create(pthread_t *pthread, const pthread_attr_t *attr, void *(strat)(void*), void *arg);
  • pthread: 保存线程ID
  • attr: 传入线程各个属性设置,NULL则为默认属性
  • 新线程通过调用带有参数arg的函数start而开始执行。
线程终止

线程终止方式:

  • 线程start函数执行return语句并返回指定值
  • 线程调用pthread_exit()
  • 调用pthread_cancel()取消线程
  • 任意线程调用了exit() ,或主程序执行了return,都会导致进程中的所有线程立即终止。

pthread_exit()
将立即终止程序,且返回值可由另一线程通过pthread_join()来获取。

#include <pthread.h>
void ptrhead_exit(void *retval);

retval所指向的内容不应分配与线程栈中,防止失效。

线程ID

进程内部的每一个线程都有一个唯一标识,称为线程ID。
获取线程ID的方法:

  • pthread_create() 返回给调用者
  • pthread_self()函数获得自己的线程ID
    pthread_self()
#include <pthread.h>
pthread_t pthread_self(void);

线程ID的作用:

  • 不同的Pthreads函数利用线程ID来标识要操作的目标线程。(pthread_join\pthread_detach()\pthread_cancel()\pthread_kill())

pthread_equal() 检查两个线程ID是否相同 (ID相同则返回非0,不同则返回0)

#include <pthread.h>
int pthread_equal(pthread_t t1, pthread_t t2);
连接(joining)已终止的线程

函数**ptrhead_join()**等待由pthred_t标识的线程终止。
如果线程已经终止,ptrhead_join()会立即返回。

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
  • 若retval为非空指针,将会保存线程终止时返回值的拷贝,该返回值亦即线程调用return 或者 pthread_exit()时所指定的值。
  • 向pthread_join传入一个之前已然连接过的线程ID,将会导致无法预知的行为。
  • 若线程并未分离,则必须使用pthread_join()来进行连接。如果未能连接,那么线程终止时将产生僵尸线程。除了浪费系统资源以外,僵尸线程若积累过多,应用将再也无法创建新的线程。
线程的分离

默认情况下,线程是可连接的,线程退出时,可通过pthread_join获得返回状态,但当不关心返回状态时,则可以设置为分离属性,让系统自动清理移除。

#include <pthread>
int pthread_detach(pthread_t thread);

常见用法:pthread_detach(pthread_self());


线程同步

保护对共享变量的访问:互斥量
  • 静态分配的互斥量,初始化静态互斥量PTHREAD_MUTEX_INITIALIZER
#include <pthread.h>

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t  *mutex);
int pthread_mutex_unlock(pthread_mutex_t  *mutex);
  • 防止互斥量死锁的方案:

    • 定义互斥量的层级关系,总是以相同顺序对改组互斥量进行锁定。
    • 较少使用:尝试一下,然后恢复。 pthread_mutex_trylock(); 如果trylock失败,则将释放该线程所有互斥量。
  • 动态初始化互斥量

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr);

使用场景:

  • 动态分配于堆中的互斥量。例如,动态创建针对某一结构的链表,表中每个结构都包含一个pthread_mutex_t类型字段来存放互斥量,借以保护对该结构的访问。

  • 互斥量是在栈中分配的自动变量

  • 初始化经由静态分配,且不使用默认属性的互斥量.

  • 关于互斥量的属性:

  • 销毁互斥量

#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
通知状态的改变:条件变量
  • 静态条件变量:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  • 条件变量的主要操作是发送信号(signal)和等待(wait)。
  • 发送信号操作通知一个或多个处于等待的线程,某个共享变量的状态已经改变。
  • 等待操作是指在收到一个通知前一直处于阻塞状态。
#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cont_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

pthread_cond_signal() 和 pthread_cond_broadcast() 差别在于二者对于阻塞pthread_cond_wait()的多个线程处理方式不同。
pthread_cond_signal()只保证唤醒至少一条遭到阻塞的线程
pthread_cond_broadcast() 则会唤醒所有遭到阻塞的线程。

pthread_cont_timewait() 指定等待通知的休眠上线。

  • 动态条件变量
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

int pthread_cond_destroy(pthread_cond_t *cond);

线程取消

  • 取消函数
#include <pthread.h>
int pthread_cancel(pthread_t thread);
  • 取消状态
    PTHREAD_CANCEL_DISABLE,不允许取消,阻塞
    PTHREAD_CANCEL_ENABLE, 允许取消
  • 类型
    PTRHEAD_CANCEL_ASYNCHRONOUS,可能会在任何时间点取消
    PTHREAD_CANCEL_DEFERED,挂起,直到到达取消点
  • 设置函数
#include <pthread.h>

int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
  • 手动设置取消点
#include <pthread.h>

void pthread_tescancel(void); 
  • 清理函数
#include <pthread.h>

void pthread_cleanup_push(void (*routime)(void*), void *arg);//放线程头
void pthread_cleanup_pop(int execute);//放线程尾

当execute不为0,则表示清理函数一定会执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值