线程:
一个进程包含多个线程,共享进程的全局内存区域
线程的内存分布:
线程会继承进程部分信息,也会有一些独立的信息:详见pthread
线程函数的返回值与errno的值相同,可以对此进行防御式编程。
详见pthread
pthread_create();//线程创建
pthread_exit();//线程终止
pthread_self();//返回PID
pthread_equal();//判断PID是否相等
pthread_join();//等待线程终止,可以获取线程返回值
pthread_detach();//分离线程,不关心其返回值,让其成为后台线程
线程属性pthread_attr_t类型
线程同步:
1.互斥量:
1)静态分配 pthread_mutex_t mtx = PTHREAD_MUTEX_INITALIZER;
2)动态分配,使用函数:pthread_init();pthread_mutex_destory();
3)加锁与解锁:pthread_mutex_lock(); pthread_mutex_unlock();
4)其他解锁函数:pthread_mutex_trylock(); pthread_mutex_timelock();
互斥量的死锁避免:应该使用相同顺序对一组互斥量加锁。
2.条件变量:
1)静态分配 pthread_cond_t cond = PTHREAD_COND_INITALIZER;
2)动态分配:pthread_cond_init();pthread_cond_destory();
3)操作参数:
pthread_cond_signal();//唤醒至少一条阻塞线程
pthread_cond_broadcast();//唤醒所有阻塞线程
pthread_cond_wait();//使用时,先对参数中的mutex解锁,然后阻塞到条件满足唤醒线程再上锁
pthread_cond_wait();//加上定时器cond_wait
//以下方式使用较少,了解即可
3.读写锁:
详见:rwlock
4.自旋锁:
pthread_spin_init();等等。与mutex类似,但是不是使进程阻塞,而是一直处于忙等待(自旋)的阻塞状态。用于持有锁时间短的情况。常用于底层,实现其他锁机制。
5.屏障:
pthread_barrier_init();等等。协调多个线程,直到合作线程到达某一点
线程安全与线程存储
线程安全函数:
pthread_once();//无论多少线程调用,只执行一次。在C++的DCLP可以配合使用(C++11多线程标准库中也有类似的函数)
线程特有数据:
为线程单独开辟的数据区(与pthread_once()配合)
线程特有数据会包含一个全局(进程范围内)数组,存在线程特有数据的key信息。
每个线程包含一个数组存放分配的线程特有数据块的指针。
static void destructor(void* ptr)
{
free(ptr);
}
void thread_perr(char* f, int s)
{
fprintf(stderr, "%s : %s", f, strerror(s));
}
static void make_key()
{
int s;
s = pthread_key_create(&key, destructor);//在线程退出的时候调用destructor
if (s != 0)
thread_perr("pthread_key_create", s);
}
void func()
{
void *ptr;
int s;
s = pthread_once(&key_once, make_key);//保证只创建一次
if (s != 0)
thread_perr("pthread_once", s);
if ((ptr = pthread_getspecific(key)) == NULL) //获取key的缓冲区地址 { {
ptr = malloc(OBJECT_SIZE);//分配内存
s = pthread_setspecific(key, ptr);//保存缓冲区地址
if (s != 0)
thread_perr("pthread_getspecific", s);
//...其他操作
}
在全局或静态变量前包含__thread关键字
线程取消:
pthread_cancel();
pthread_setcancelstate();
pthread_setcancelstyle();
线程取消请求发送后会一直阻塞到线程抵达cancellation point。是cancellation point详见:pthread
pthread_testcancel();//测试可取消性
线程清理:
pthread_cleanup_push();pthread_cleanup_pop();//向线程清理函数栈注册和移出函数 详见:pthread_cleanup_push 与pthread_cleanup_pop
异步取消:
设置取消类型为PTHREAD_CANCEL_AYSNCCHRONOUS,可实现线程异步取消,
异步取消任何时点即可取消(清理函数也无法获取线程取消调用时的具体情况,因此可异步取消的线程不分配任何资源,不获取mutex等等)