本文,记录linux-pthread学习。
这是新的笔记方式,着重直接应用、调试思考,直接面向产出。
快速掌握api流程(运行与调试apue-threads代码示例)
- 打印pthreadid
- pthread_create
- getpid:在此例子,用于观察两个线程的进程号是否相同
- pthread_self返回线程ID,打印需要使用%lu,不然出奇怪错误,同时转为long输出
- 观察线程退出状态exitstatus
- return与pthread_exit(可移植较强的方式)区别
- pthread_join:阻塞等待目标线程退出(目标线程不分离情况下)、它para2标识目标线程退出码
- 某线程上定义变量(占用栈内存)带来的问题(所有线程共用进程的堆栈资源,自行联想解析)
- 解决:使用全局变量(放在进程的静态变量区),使用malloc分配资源(放在进程的堆区)
- 线程清理处理程序pthread_cleanup_push、pthread_cleanup_pop(堆栈方式存放处理清理程序,所以是反序的)
- 它们俩到底是什么作用呢?链接,如果函数名一致,释放资源为主要目的。
- 互斥量同步,自行编写测试代码main,提供多个改进型程序,逐步验证线程“同步”问题
- 全局pthread_mutex_t变量初始化,选用宏PTHREAD_MUTEX_INITIALIZER
- pthread_mutex_init
- pthread_mutex_lock与pthread_mutex_unlock、pthread_mutex_timedlock
- pthread_mutex_destroy
- 读写锁,模拟工作队列,多个工作线程独自创建新的工作,并在加入队列,队列对所有线程可见(一直思考,这个能不能改进为线程池呢?)
- pthread_equal检测线程号是否相同,在此用于从队列中挑选当前线程应该执行的任务。
- pthread_rwlock_init与pthread_rwlock_destroy
- pthread_rwlock_rdlock与pthread_rwlock_wrlock、pthread_rwlock_unlock
- 设计该应用示例,它的工作原理是apue图11-1
- 同时,为了方便测试,采用pthread_detach将线程分离,自动回收资源。主线程不需调用pthread_join
- 条件锁,模拟工作队列(暂时不能弄清楚它的应用场景,所以没有编写测试代码)
- pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传给函数,函数然后自动把调用线程放到等待条件的线程列表上,对互斥量解锁。函数返回时,互斥量再次被锁住。
- pthread_cond_signal(唤醒等待该条件的所有互斥量的线程当中的一个)和pthread_cond_broadcast(同前,所有),要理解这两个函数,必须理解wait的工作原理。
- pthread_cond_init和pthread_cond_destroy
- 屏障锁,协调多个线程并行工作,支持协调任意数量线程,例程实现并发排序
- pthread_barrier_init和pthread_barrier_destroy
- pthread_barrier_wait,注意,到达屏障线程数一旦满足,所有等待线程同时继续执行
- 同步例程功能测试(fig11.10-16),部分已经修改,增加稳定性和修复bug
- fig11.10一个mutex,两个线程,共享一个计数资源
- fig11.11两个mutex,三个线程,共享一个hash表,里面集多个资源(锁机制复杂,因为需要排序)
- hashlock用于锁住hash table
- fp-f_lock用于锁住f_count及其资源
- 这是锁的粒度细,过多的所开销会使系统性能受到影响
- fig11.12两个mutex(实际使用到了一个锁),三个线程,共享一个hash表,里面集多个资源(锁机制简单,原理与1相同)
- hashlock用于锁住hash table里面所有f_count及其资源
- 则是锁的粒度粗,会出现很多线程阻塞等待相同的锁,这可能并不能改善并发性
- fig11.13定时阻塞等待锁资源,仅为验证pthread_mutex_timedlock的使用
- fig11.14一个读写锁,一个工作队列,每个线程对应一个工作请求,多个线程完成相同功能,并且能够找到对方。
- fig11.15一个条件锁,一个互斥锁,配合实现唤醒单个等待线程
- ex11.1一个条件锁,一个互斥锁,实现唤醒所有等待线程,该示例更容易理解API的实质,尤其是wait的工作机制
- fig11.16一个屏障锁,多线程排序随机数,最后回到主线程里合并子数组(已经部分有序),然后输出至stdout
产生疑问
- 一个mutex,一个线程占用,另一个线程等待,占用线程直接执行pthread_mutex_destroy,等待线程会怎么办?
- mutex全局静态与局部init区别?:静态初始化只能唯一地:声明、定义、宏初始化,不能单独“引用”宏初始化
- pthread_mutex_timedlock的时间,是绝对时间。需要配合clock_gettime使用。
- 线程间的堆栈是否共享,其共享方式或划分方式如何?假设:在里面定义个变量,其他线程也可以知道?
- pthread_cond_wait的深度理解,它的工作原理是?为什么pthread_cond_broadcast能够唤醒所有?
- 做了以上测试,发现(猜测,但很有可能),使用各种pthread_锁_destroy函数,销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。由于在Linux中,互斥锁并不占用任何资源,因此Linux-Threads中的pthread_锁_destroy ()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。
- 自旋锁是个人没有学习过的,因为暂时不需要会用到