当线程运行在同样的线程空间,线程们共享同样的内存和资源。这使它变得很容易对于线程来通信和共享数据,尽管它会发生两种问题:线程阻塞和内存不一致由于线程的同步对共享资源的修改。在这些情况下,线程同步变得很重要。线程同步提供了这机制来确保同步运行的线程并不执行同一块代码在同一时间。与Java线程类似,这POSIX Thread API也提供同步的函数。这章主要讲述两种有POSIX Threads提供的同步机制:
Mutexes(互斥信号量)被包含在同一代码中并不能在同一时间执行。
Semaphores(资源信号量)通过指定的资源数量来控制获得资源。如果没有资源,这调用线程等待资源被释放后执行。
使用互斥信号量的同步线程:
POSIX Thread API通过pthread_mutex_t数据类型来展示互斥信号量给原生代码。这
POSIX Thread API提供了一套函数来和互斥信号量通信。使用之前,这互斥信号量应该被先初始化。
初始化信号量:
这POSIX Thread API提供两种方式初始化信号量:pthead_mutex_init函数和PTHREAD_MUTEX_INITIALIZER宏。这pthread_mutex_init函数能够被用来初始化这个信号量。
int pthread_mutex_init(pthread_mutex_t* mutex,const pthread_mutexattr_t* attr);
这个pthread_mutex_init函数的两个参数,一个互斥信号量的指针来初始化和一个phread_mutexattr_t结构定义这互斥信号量的指针。如果第二个参数被设置为NULL,这默认的属性被使用。如果这默认属性时足够,代替者pthread_mutex_init函数,这PTHREAD_MUTEX_INITIALIZER宏是最恰当的。
pthread_mutex_t mutex=PTHREAD_MUTEX_INITALIZER;
基于成功的初始化,这互斥信号量的状态变得被初始和unlocked,和这函数返回0,否则它将返回这错误代码。
锁定互斥信号量
这pthread_mutex_lock函数被用来获得共同的代码通过锁定已经初始化的信号量。
int pthread_mutex_lock(pthread_mutex_t* mutex);
这个函数的参数是这互斥信号量的指针。如果这互斥信号量已经被锁定了,这调用先被阻止直到互斥信号量被解锁。成功的情况下,返回0;否则它返回这错误代码。
解锁信号量
基于完成执行这严格的代码区间,这互斥信号能够解锁使用pthread_mutex_unlock函数。
int pthread_mutex_unlock(pthread_mutex_t* mutex);
成功执行时返回0;否则返回错误代码。
pthread_mutex_destroy销毁互斥信号量。
使用资源信号量同步POSIX Threads:
并不像其他的POSIX函数,这个POSIX资源信号量被定义在一个不同的头文件,这semaphore.h中。
#include<semaphore.h>
这POSXI资源信号量通过sem_t 数据类型被展示给原生代码。这POSIX 资源信号量API提供了一套函数对于来自原生代码的资源信号量相互制约。使用之前,这资源信号量必须先被初始化。
初始化资源信号量:
这POSIX资源信号量API同sem_init函数来初始化这资源信号量。
extern int sem_init(sem_t* sem,int pshared,unsigned int value);
他的三个参数:一个资源信号量的指针被初始化,这共享的标记和它初始化的值。一旦成功返回0,否则返回-1;
锁定资源信号量
一旦这资源信号量被恰当初始化,线程能够实用sem_wait函数来减少这信号量的数量:
extern int sem_wait(sem_t* sem);
这函数信号量的指针为参数。如果资源信号量的值是大于0的,这锁定成功和这信号量的值就会减少。如果这信号量的值为0,调用线程就会阻止直到这资源信号里通过unlocking来增加。一旦成功,这函数返回0;否则返回-1;
解锁资源信号量
一旦完成这执行关键代码区,这线程能偶解锁资源信号量通过这sem_post函数。
extern int sem_post(sem_t* sem);
当这资源信号量被解锁通过sem_post函数,它的值增加1.调度策略决定那个线程得到执行。一旦成功返回0,否则返回-1;
销毁资源信号量:
一旦这资源信号量不在被需要,它可以被销毁通过这sem_destroy函数。
extern int sem_destroy(sem_t* sem);
这函数去资源信号量的指针作为参数。销毁一个资源信号量其他的线程可能被阻塞可能导致不确定的行为。一旦函数返回0,成功。否则-1.
对于POSIX线程优先级和调度策略:
调度策略,和线程优先级,以一个可能执行的顺序的对线程列表排序。这部分简要的浏览这些调度策略和这线程的优先级。
Posix线程的调度策略:
这POSIX线程指定需要一套调度策略来实现。这最流行使用的策略如下:
SCHED_FIFO:先进先出的调度策略。
SCHED_RR:这round_robin调度策略防止独占CPU资源,循环执行。
他们在sched.h头文件中。这调度策略sched_policy域pthread_attr_t中指定在pthread_create函数中或通过这个函数的运行期间。
int poilcy;
struct sched_param const* param);
PoSix 线程的优先级:
这POSIX Thread API也提供函数来矫正基于调度策略的线程优先级。这线程的优先级被定义使用sched_priority域通过pthread_attr_t结构来使用pthread_create函数时,或者通过pthread_setschedparam函数在运行期间和提供优先级在sched_param结构。则最小和最大的优先级值基于调度策略是不同的。这应用程序能够查询这些数字通过使用sched_get_priority_max和sched_get_priority_min函数。