14 多线程编程
创建线程和结束线程
#include
int pthread_create(pthread_t* thread, const pthread_attr_* attr, void* (*start_routine)(void*), void* arg);
pthread_t是一个整形数,Linux上几乎所有的资源标示符都是一个整形数,比如socket、各种ipc标示符等。
int pthread_exit(void* retval);
一个进程中的所有线程都可以调用pthread_join函数来回收其他线程,即等待其他线程结束,这类似于回收进程的wait和waitpid系统调用。
int pthread_join(pthread_t thread, void** retval);
有时候我们希望异常终止一个线程,即取消线程:
int pthread_cancel(pthread_t thread);
目标线程可以决定是否允许被取消以及如何取消,这分别由如下两个函数完成:
int pthread_setcancelstate(int state, int* oldstate);
int pthread_setcanceltype(int type, int* oldtype);
线程属性:
pthread_attr_t 结构体定义了一套完整的线程属性,
#include
#define __SIZEOF_PTHREAD_ATTR_T 36
typedef union{
char __size[__SIZEOF_PTHREAD_ATTR_T];
long int __align;
}pthread_attr_t;
线程库定义了一系列函数来操作pthread_attr_t类型的变量。
POSIX信号量:
函数的名字都以sem_开头,并不像大多数线程函数那样以pthread_开头。常用的POSIX信号量函数是下面5个:
#include
int sem_init(sem_t* sem, int pshared, unsigned int value);//pshared指定信号量的类型,如果值为0,就表示这个信号量是当前进程的局部信号量,否则该信号量可以在多个进程间共享。value指定信号量的初始值。
int sem_destroy(sem_t* sem);
int sem_wait(sem_t* sem);//以原子操作的方式将信号量的值减1
int sem_trywait(sem_t* sem);
int sem_post(sem_t* sem);//以原子操作的方式将信号量的值加1
互斥锁:
#include
int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* mutexattr);
int pthread_mutex_destroy(pthread_mutex_t* mutex);
int pthread_mutex_lock(pthread_mutex_t* mutex);
int pthread_mutex_trylock(pthread_mutex_t* mutex);
int pthread_mutex_unlock(pthread_mutex_t* mutex);
可以使用如下方式来初始化一个互斥锁:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITHIALIZER;
宏PTHREAD_MUTEX_INITIONALIZER实际上只是把互斥锁的各个字段都初始化为0.
互斥锁的属性:
pthread_mutexattr_t结构体定义了一套完整的互斥锁属性。线程库提供了一系列函数来操作pthread_mutexattr_t类型的变量:
int pthread_mutexattr_init(pthread_mutexattr_t* attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr);
int pthread_mutexattr_getshared(const pthread_mutexattr_t* attr, int* pshared);
int pthread_mutexattr_setshared(pthread_mutexattr_t* attr, int pshared);
int pthread_mutexattr_gettype(const pthread_mutexattr_t* attr, int* type);
int pthread_mutexattr_settype(pthread_mutexattr* attr, int type);
互斥锁的两种常用属性:pshared和type. pshared指定是否允许跨进程共享互斥锁,其可选值由两个:
PTHREAD_PROCESS_SHARED 可以被跨进程共享
PTHREAD_PROCESS_PRIVATE 只能被和锁的初始化线程隶属于同一个进程的线程共享。
属性type指定互斥锁的类型。linux支持4中类型的互斥锁:
PTHREAD_MUTEX_NORMAL
PTHREAD_MUTEX_ERRORCHECK
PTHREAD_MUTEX_RECURSIVE
PTHREAD_MUTEX_DEFAULT
条件变量:
用于在线程之间同步共享数据的值。
int pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* cond_attr);
int pthread_cond_destroy(pthread_cond_t* cond);
int pthread_cond_broadcast(pthread_cond_t* cond);
int pthread_cond_signal(pthread_cond_t* cond);
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
初始化:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
多线程环境:
可重入函数:
如果一个函数能被多个线程同时调用且不发生竞态条件,则我们称它是线程安全的,或说它是可重入函数。linux库函数只有一小部分是不可重入的。这些库函数之所以不可重入,主要是因为其内部使用了静态变量。不可重入库函数的可重入版本是在原函数名尾部加上 _r。
线程和信号:
在多线程环境下我们应该使用如下所示的pthread版本的sigprocmask函数来设置线程信号掩码:
#include
#include
int pthread_sigmask(int how, const sigset_t* newmask, sigset_t* oldmask);
阅读(1534) | 评论(0) | 转发(0) |