文章目录
8.线程:
8.1线程是操作系统调度的最小(基本)单位
8.2return,pthread_exit,pthread_cancel,exit,_exit,_Exit 退出线程的区别:
1).如果进程中的任意线程调用 exit, _exit 或者 _Exit,那么将会导致整个进程终止,这里需要注意!
2).exit 会调用进程终止函数,而 _exit 和 _Exit 不会调用
8.3注意并行,并发和串行的区别
8.4获取自己的线程 id:
pthread_self
8.5创建新的线程:
pthread_create
8.6终止线程:
pthread_exit,return,pthread_cancel
8.7回收线程:
# 如果一个线程结束后未被其他线程调用 pthread_join 回收,将会成为僵尸线程,僵尸线程除了可以被其他线程回收,还可以随着进程一起被回收
pthread_join
8.8取消点:
许多函数都可以作为取消点,当没有取消点时,可以使用 pthread_testcancel 函数产生取消点
8.9分离线程:
# 分离线程后,该线程终止时会自动回收资源
pthread_detach
8.10线程清理处理函数:
8.10.1线程通过函数 pthread_cleanup_push 和 pthread_cleanup_pop 分别负责向调用线程的清理函数栈中添加和移除清理函数
8.10.2清理函数栈中的清理函数执行的条件:
1).线程调用 pthread_exit 退出时
2).线程响应取消请求时
3).用非 0 参数调用 pthread_cleanup_pop 时
8.11线程安全:
8.11.1线程栈:
每个线程都有自己独立的栈空间,因此局部变量互不干扰
8.11.2可重入函数:
该函数被多个执行流(包括由信号处理函数所产生的执行流)同时调用是否总能产生正确的结果,如果每次都能产生预期的结果则表示该函数是一个可重入函数
8.11.3线程安全函数:
该函数被多个线程(不包括由信号处理函数所产生的执行流)同时调用是否总能产生正确的结果,如果每次都能产生预期的结果则表示该函数是一个线程安全函数
8.11.4一次性初始化:
pthread_once
8.11.5线程特有数据:
# 使用这3个函数
pthread_key_create
pthread_setspecific
pthread_getspecific
8.11.6线程局部存储:
__thread
8.11.7线程与信号:
8.11.7.1线程的信号掩码:
pthread_sigmask 和 sigprocmask 的区别:
# sigprocmask 只能用于单线程进程,fork 的子进程拥有一份屏蔽信号拷贝
# pthread_sigmask 用于多线程,pthread_create 的新线程拥有一份屏蔽信号拷贝
8.11.7.2多线程和单线程处理信号的原则不同:
1).单线程处理信号的方式:
# 先注册信号处理函数,当信号异步发生时,调用处理函数来处理信号
# 信号处理函数的实现,有着许多的限制:
# 比如有一些函数不能在信号处理函数中调用
# 再比如一些函数调用时会被异步的信号给中断(interrupt)
2).多线程处理信号的方式:
# 将对信号的异步处理,转换成同步处理
# 也就是说 —— 用一个线程专门的来"同步等待"信号的到来,而其它的线程可以完全不被该信号中断/打断(interrupt)
8.11.7.3向线程发送信号:
pthread_kill,pthread_sigqueue 向同一进程中的某个指定的线程发送信号
8.11.7.4异步信号安全函数:
1).可以通过 man 7 signal 来查询
2).按照严格程度从强到弱排序:可重入函数,异步信号安全函数,线程安全函数
3).可以为线程安全函数所在的线程设置信号掩码,使其成为异步信号安全函数
8.11.8线程同步:
8.11.8.1作用:
对共享资源的访问进行保护
8.11.8.2互斥锁:
1).pthread_mutex_t
2).互斥锁初始化:
# 使用 PTHREAD_MUTEX_INITIALIZER 宏初始化互斥锁(静态初始化)
PTHREAD_MUTEX_INITIALIZER
# 使用 pthread_mutex_init 函数初始化互斥锁(动态初始化)
pthread_mutex_init
3).销毁互斥锁:
# 动态初始化需要销毁,而静态初始化不需要销毁,在程序结束时会自动释放
pthread_mutex_destroy
4).互斥锁加锁和解锁:
# 阻塞加锁
pthread_mutex_lock
# 非阻塞加锁
pthread_mutex_trylock
# 释放锁
pthread_mutex_unlock
5).避免互斥锁死锁的方法:
定义互斥锁的层级关系
8.11.8.3条件变量:
1).pthread_cond_t
2).条件变量初始化:
# 使用宏 PTHREAD_COND_INITIALIZER 初始化互斥锁(静态初始化)
PTHREAD_COND_INITIALIZER
# 使用函数 pthread_cond_init 初始化互斥锁(动态初始化)
pthread_cond_init
3).销毁条件变量:
# 动态初始化需要销毁,而静态初始化不需要销毁,在程序结束时会自动释放
pthread_cond_destroy
4).通知和等待条件变量:
# 通知
pthread_cond_signal
pthread_cond_broadcast
# 等待
pthread_cond_wait
5).条件变量一般结合互斥锁一起使用
8.11.8.4自旋锁:
pthread_spinlock_t
# 自旋锁初始化:
pthread_spin_init
# 销毁自旋锁:
pthread_spin_destroy
# 自旋锁加锁和解锁:
pthread_spin_lock,pthread_spin_trylock,pthread_spin_unlock
8.11.8.5读写锁:
1).读写锁有三种状态:
读加锁状态,写加锁状态和不加锁状态
2).pthread_rwlock_t
3).读写锁初始化:
# 可以使用宏 PTHREAD_RWLOCK_INITIALIZER
PTHREAD_RWLOCK_INITIALIZER
# 可以使用函数 pthread_rwlock_init
pthread_rwlock_init
4).销毁读写锁:
pthread_rwlock_destroy
5).读写锁的上锁和解锁:
pthread_rwlock_rdlock
pthread_rwlock_wrlock
pthread_rwlock_tryrdlock
pthread_rwlock_trywrlock
pthread_rwlock_unlock