线程ID、线程属性、线程撤销
线程ID
pthread_equal()
函数:确认两个线程是否相同
- 原型
int pthread_equal(pthread_t t1, pthread_t t2);
pthread_self()
函数:返回当前线程ID
- 原型:
pthread_t pthread_self(void);
- 示例
if (!pthread_equal (pthread_self (), other_tid))
{
pthread_join (other_tid, nullptr);
}
线程属性
精细调整线程的行为
设置线程属性的流程
-
创建
pthread_attr_t
类型的对象 -
调用
pthread_attr_init()
函数初始化线程缺省属性,传递指向该线程属性对象的指针原型:
int pthread_attr_init(pthread_attr_t *attr);
-
对线程属性进行必要修改
-
调用
pthread_crerate()
函数时传递指向线程属性对象的指针 -
调用
pthread_attr_destroy()
函数清除线程属性对象,pthread_attr_t
对象本身并没有被销毁,因而可以调用pthread_attr_init()
函数再次初始化 原型:
int pthread_attr_destroy(pthread_attr_t *attr);
线程属性说明
- 单一线程属性对象可以用于创建多个线程
- 线程创建后,继续保留线程属性对象本身并没有意义
- 对于大多数Linux程序,线程最重要的属性为分离状态(
detach state
)
线程分类
-
可联线程(
joinable thread
): 缺省设置,终止时并不自动清除(类似僵尸进程),主线程必须调用pthread_join()
获取其返回值,此后才能清除 -
分离线程(
detached thread
):结束时自动清除,不能调用pthread_join()
进行线程同步 -
可联线程可通过
pthread_detach()
函数分离,分离线程不能再次联结 原型:
int pthread_detach(pthread_t thread);
pthread_attr_setdeatchstate()
函数:设置线程分离属性
-
原型
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
-
传递线程属性对象指针和分离线程设置参数
PTHREAD_CREATE_DETACHED
pthread_attr_getdetachstate()
函数:获取线程分离属性
-
原型
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
#include <pthread.h>
void *ThreadFunc (void *arg)
{ }
int main ()
{
pthread_attr_t attr;
pthread_t thread;
//初始化线程属性
pthread_attr_init (&attr);
//设置线程属性的分离状态
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
//创建线程
pthread_create (&thread, &attr, &ThreadFunc, nullptr);
//清除线程属性对象
pthread_attr_destroy (&attr);
//无需联结该线程
return 0;
}
线程撤销
pthread_cancel()
函数:撤销线程
-
原型:
int pthread_cancel(pthread_t thread);
-
已撤销的线程可以来联结,且必须联结欸,以释放其资源,除非其为分离线程
线程撤销类型与状态
- 异步可撤销:在其执行的任何时刻都可撤销
- 同步可撤销:线程可撤销,但撤销操作首先进入队列排队,在线程执行到特定撤销点时才可撤销
- 不可撤销:撤销不可撤销线程的企图被系统忽略,且没有任何消息反馈
pthread_setcanceltype()
函数:设置线程的撤销类型
-
原型
int pthread_setcanceltype(int type, int *oldtype);
-
参数:
type
为撤销类型,oldtype
用于保存原始线程撤销类型,NULL
表示不保存 -
PTHREAD_CANCEL_ASYNCHRONOUS
:线程异步可撤销 -
PTHREAD_CANCEL_DEFERRED
:线程同步可撤销,即延迟到下一撤销点时撤销
pthread_setcanceltype()
函数:设置线程的撤销状态
-
原型:
int pthread_setcanceltype(int type, int *oldtype);
-
第一个参数
state
为可撤销状态,第二个参数oldstate
用于保存原始线程的可撤销状态,NULL
表示不保存 -
PTHREAD_CANCEL_ENABLE
:线程可撤销 -
PTHREAD_CANCEL_DISABLE
:线程不可撤销 -
线程的撤销状态可多次设置
pthread_testcancel()
函数:设置撤销点
-
原型
void pthread_testcancel(void);
-
在线程函数中调用
pthread_testcancel()
函数设置撤销点 -
建议:周期性地设置撤销点,保证线程函数内部每隔一些代码就有一个撤销点,以保证资源能够正确释放
使用撤销状态构造临界区(critical section)
- 临界区:要么全部执行,要么一条都不会执行的代码段
- 设置线程的撤销状态,线程一旦进入临界区,就必须等到离开临界区,才可以被撤销
void Transfer (double *accounts, int from, int to, double amount)
{
int ocs;
//数据有效性检查代码在此,确保转账操作合法有效
//将线程设置为不可撤销的,进入临界区
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &ocs);
accounts[to] += amount;
accounts[from] -= accounts;
//恢复线程的撤销状态,离开临界区
pthread_setcancelstate (os, NULL);
}