《UNIX环境高级编程》(APUE) 笔记第十一章 - 线程 (2)

线程可以通过 pthread_cancel 函数来请求 取消同一进程中的其他线程

#include <pthread.h> int pthread_cancel(pthread_t tid); //返回值:若成功,返回0;否则,返回错误编号

默认情况下,pthread_cancel 函数会使得 \(tid\) 标识的线程的行为表现为如同调用了参数为 PTHREAD_CANCELED 的 pthread_exit 函数,但是,线程可以选择忽略取消或者控制如何被取消。

pthread_cancel 并不等待线程终止,它仅仅提出请求。

线程可以安排它退出时需要调用的 线程清理处理程序

#include <pthread.h> void pthread_cleanup_push(void (*rtn)(void *), void *arg); void pthread_cleanup_pop(int execute);

一个线程可以建立多个清理处理程序,处理程序记录在栈中,也就是说,它们的执行顺序与注册顺序相反。pthread_cleanup_pop 函数删除上次 pthread_cleanup_push 函数建立的清理处理程序。这两个函数必须在与线程相同的作用域中以匹配的对的形式使用。

当线程执行以下动作时,清理函数 \(rtn\) 是由 pthread_cleanup_push 函数调度的,调用时只有一个参数 \(arg\)

调用 pthread_exit

响应取消请求时

用非零 \(execute\) 参数调用 pthread_cleanup_pop

可以看到,如果线程是通过从它的启动例程中返回而终止的话,它的清理处理程序就 不会 被调用 。

5. 进程和线程原语的比较

《UNIX环境高级编程》(APUE) 笔记第十一章 - 线程

6. 线程同步

当一个线程可以修改的变量,其他线程也可以读取或修改的时候,需要对线程进行 同步 ,确保它们在访问变量的存储内容时不会访问到无效的值。

线程使用 ,同一时间只允许一个线程访问该变量。

7. 互斥量

互斥量 (mutex) 从本质上说是一把锁,在访问共享资源前对互斥量进行设置( 加锁 ),在访问完成后释放互斥量( 解锁 )。对互斥量加锁以后,任何其他试图再次对互斥量加锁的线程都会被阻塞,直到当前线程释放该互斥锁。

互斥变量 是用 pthread_mutex_t 数据类型表示的。可以通过将其设置为 PTHREAD_MUTEX_INITIALIZER 进行初始化(只适用于静态分配的互斥量),也可以通过 pthrsisuoead_mutex_init 函数进行初始化。如果动态分配互斥量(如调用 malloc ),在释放内存前需要调用 pthread_mutex_destroy

#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); //两个函数的返回值:若成功,返回0;否则,返回错误编号

\(attr\) 是互斥量属性,设为 NULL 则使用默认属性。

使用 pthread_mutex_lock 对互斥量进行加锁,使用 pthread_mutex_unlock 对互斥量进行解锁:

#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthraed_mutex_unlock(pthread_mutex_t *mutex); //所有函数的返回值:若成功,返回0;否则,返回错误编号

如果线程不希望被阻塞,可以使用 pthread_mutex_trylock 尝试对互斥量进行加锁。如果调用此函数时互斥量处于未锁住状态,则此函数将锁住互斥量,不会出现阻塞直接返回 \(0\) ,否则函数不能锁住互斥量,返回 EBUSY 。

8. 避免死锁

死锁产生的 原因

线程对用一个互斥量加锁两次,它自身会陷入死锁状态

两个线程都在相互请求另一个线程拥有的资源

如果需要对多个互斥量加锁,可以通过 控制互斥量加锁的顺序 来避免死锁的发生。有时对互斥量排序很困难,可以先释放占有的锁,然后过一段时间再试,这种情况可以使用 pthread_mutex_trylock 接口避免死锁。(如果已经占有某些锁而且 pthread_mutex_trylock 接口返回成功,就可以前进,如果不能获取锁,就可以先释放已经占有的锁,做好清理工作,然后过一段时间再重新试 )。

9. 函数 pthread_mutex_timedlock

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjgyx.html