一、几个需要明确的概念
1.线程的可结合(joinable)
一个可结合的线程能够被其他线程回收其资源和杀死,在被其它线程回收之前,它的存储器资源(如栈)是不释放的。
2.线程分离(detached)
一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。如果我们再创建线程的时候就指导不需要了解线程的终止状态,则可以通过pthread_attr_t结构中的detachstate线程属性,让线程以分离状态启动。
在使用pthread时为了避免线程的资源再线程结束时不能得到正确释放,从而避免产生潜在的内存泄露问题,在对待线程结束时,需要确保该线程处于detached状态,否则就需要调用pthread_join函数来对其进行资源回收。
3.线程存储(Thread Specific Data)
在多线程程序中,所有线程共享程序中的变量,现在有一全局变量,所有线程都可以使用它,改变它的值。如果每个线程希望能单独拥有它,那么就需要使用线程存储,表面上看起来是一个全局变量,所有线程都可以使用它,而它的值再每一个线程中又是单独存储的,这个就是线程存储的意义。
二、数据类型
pthread_t:线程句柄
pthread_attr_t:线程属性
pthread_mutext_t:互斥锁
pthread_mutexattr_t:互斥锁属性
pthread_cond_t:条件变量
pthread_condattr_t:条件变量属性
pthread_key_t:数据键
三、基本函数
1.pthread_create:创建一个新线程
头文件:#include <pthread.h>
函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
1)thread--线程的标示符
2)attr--线程的属性设置
3)start_routine--线程函数的起始
4)arg--给start_routine传递的参数
返回值:成功0 失败-1
2.pthread_join:等待一个线程的结束,并回收其资源
头文件:#include <pthread.h>
函数原型:int pthread_join(pthread_t thread, void **retval);
1)thread--线程的标示符
2)retval--退出线程的返回值
返回值:成功0,失败返回一个非负数值
3.pthread_exit:终止当前线程
头文件:#include <pthread.h>
函数原型:void pthread_exit(void *retval);
1)retval--退出线程的返回值
4.pthread_cancel:中断另外一个线程的运行
头文件:#include <pthread.h>
函数原型:int pthread_cancel(pthread_t thread);
1)thread--要中断线程的标识符
返回值:成功返回0,失败返回一个非负数值
5.pthread_attr_init:初始化线程的属性
头文件:#include <pthread.h>
函数原型:int pthread_attr_init(pthread_attr_t *attr);
1)attr--线程属性
返回值:成功返回0,失败返回一个非负数值
6.pthread_attr_setdetachstate:设置脱离状态的属性
头文件:#include <pthread.h>
函数原型:int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
1)attr--线程属性
2)detachstate--分离状态标示(1)PTHREAD_CREATE_DETACHED (2)PTHREAD_CREATE_JOINABLE
返回值:成功返回0,失败返回一个非负数值
7.pthread_attr_getdetachstate:获取脱离状态的属性
头文件:#include <pthread.h>
函数原型:int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
1)attr--线程属性
2)detachstate--分离状态标示(1)PTHREAD_CREATE_DETACHED
(2)PTHREAD_CREATE_JOINABLE
返回值:成功返回0,失败返回一个非负数值
使用示例:创建一个detach线程
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, THREAD_FUNCTION, arh);
8.pthread_attr_destroy:删除线程的属性
头文件:#include <pthread.h>
函数原型:int pthread_attr_destroy(pthread_attr_t *attr);
1)attr--线程属性
返回值:成功返回0,失败返回一个非0数值
9.pthread_kill:向线程发送一个信号
头文件:#include <signal.h>
函数原型:int pthread_kill(pthread_t thread, int sig);
1)thread--线程标示符
2)sig--发送信号标示
返回值:成功返回0,失败返回一个非0数值并且没有信号发送出去
四、同步函数--用于mutex和条件变量
Linux下为了多线程同步,通常用到锁的概念,posix下抽象了一个锁类型的结构pthread_mutex_t,通过对该结构的操作,去判断该资源是否可以访问,加锁后别人无法打开,当锁没有关闭资源才能进行访问。
以下函数如果在linux系统上无法man到,可以进行安装:sudo apt-get install manpages-posix-dev
1.pthread_mutex_init:初始化互斥锁
头文件:#include<pthread.h>
函数原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
1)mutex--互斥锁
2) attr--互斥锁属性
返回值:成功返回0
2.pthread_mutex_destroy:删除互斥锁
头文件:#include <pthread.h>
函数原型:int pthread_mutex_destroy(pthread_mutex_t *mutex);
1)mutex--互斥锁
返回值:成功返回0
3.pthread_mutex_lock:占有互斥锁(阻塞操作)
头文件:#include <pthread.h>
函数原型:int pthread_mutex_lock(pthread_mutex_t *mutex);
1)mutex--互斥锁
返回值:成功返回0
4.pthread_mutex_trylock:试图占有互斥锁(不阻塞操作)
当互斥锁空闲时将占有该锁;否则立即返回
头文件:#include <pthread.h>
函数原型:int pthread_mutex_trylock(pthread_mutex_t *mutex);
1)mutex--互斥锁
返回值:成功返回0
5.pthread_mutex_unlock:释放互斥锁
头文件:#include <pthread.h>
函数原型:int pthread_mutex_unlock(pthread_mutex_t *mutex);
1)mutex--互斥锁
返回值:成功返回0
6.pthread_cond_init:初始化条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
头文件:#include <pthread.h>
函数原型: int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
1)cond--条件变量
2)attr--条件变量属性
返回值:成功返回0
7.pthread_cond_destroy:销毁条件变量
头文件:#include <pthread.h>
函数原型: int pthread_cond_destroy(pthread_cond_t *cond);
1)cond--条件变量
返回值:成功返回0
8.pthread_cond_wait:等待条件变量的特殊条件发生
头文件:#include <pthread.h>
函数原型: int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
1)cond--条件变量
2)mutex--互斥锁
返回值:成功返回0
9.pthread_cond_signal:唤醒第一个调用pthread_cond_wait而进入睡眠的线程
头文件:#include <pthread.h>
函数原型:int pthread_cond_signal(pthread_cond_t *cond);
1)cond--条件变量
返回值:成功返回0
10.pthread_key_create:分配用于标识进程中线程特定数据的键
头文件:#include <pthread.h>
函数原型: int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
1)key--数据键
2)void*--任意数据类型
返回值:成功返回0
11.pthread_setspecific:为指定线程特定数据键设置线程特定绑定
头文件:#include <pthread.h>
函数原型:int pthread_setspecific(pthread_key_t key, const void *value);
1)key--数据键
2)value--设置的数据值
返回值:成功返回0
12.pthread_getspecific:获取调用线程的键绑定,并将该绑定存储在value指向的位置中
头文件:#include <pthread.h>
函数原型:void *pthread_getspecific(pthread_key_t key);
1)key--数据键
13.pthread_key_delete:销毁现有线程特定数据键
头文件:#include <pthread.h>
函数原型:int pthread_key_delete(pthread_key_t key);
1)key--数据键
返回值:成功返回0
五、与一起工作的工具函数
1.pthread_equal:对两个线程的线程标识号进行比较
头文件:#include <pthread.h>
函数原型:int pthread_equal(pthread_t t1, pthread_t t2);
1)t1,t2进行比较的两个线程句柄
返回值:成功返回0;
2.pthread_detach: 分离线程
头文件:#include <pthread.h>
函数原型:int pthread_detach(pthread_t thread);
1)thread--线程句柄
返回值:成功返回0
3.pthread_self:查询线程自身线程标识号
头文件:#include <pthread.h>
函数原型:pthread_t pthread_self(void);
返回值:成功的话返回调用当前线程的id
六、线程间的通信方式
1.锁机制
包括互斥锁、条件变量、读写锁
1)互斥锁提供了以排他方式防止数据结构被并发修改的方法;
2)读写锁允许多个线程同时读共享数据,而对写操作是互斥的;
3)条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
2.信号量机制(Semaphore)
包括无名线程信号量和命名线程信号量。
3.信号机制(Signal)
类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。