1.1.1 信号量
使用POSIX 1003.1b信号量,有别于SystemV(ipc, semctl, semop)的信号量操作。
信号量是为线程间共享的资源计数。信号量的基础操作是:原子性的增加计数,和等待直到计数器非空并且原子性的减少计数。
1) API
1.13 #include <semaphore.h> |
信号量初始化 |
int sem_init(sem_t *sem, int pshared, unsigned int value); |
返回: 如果成功0, 失败设置 Exxx 到 error |
初始化sem指针指向的信号量,此信号量的计数为value。第2个参数指明此信号量是本地本进程使用(0)还是进程间可以使用(非0)。Linux线程当前不支持进程间使用。因此如果pshared是非0,将返回ENOSYS错误。
1.14 #include <semaphore.h> |
信号量等待函数。相当于P原语 |
int sem_wait(sem_t * sem); |
返回: 如果成功0, 失败设置 Exxx 到 error |
挂起调用此函数的线程直到sem指针指向的信号量不为0。此函数将原子性的减少信号量。
1.15 #include <semaphore.h> |
sem_wait的非阻塞版 |
int sem_trywait(sem_t * sem); |
返回: 如果成功0, 失败设置 Exxx 到 error |
此函数是sem_wait的非阻塞版。如果sem指向的信号量是非0值,那么此计数将原子性的减少并且此函数立即返回0。如果信号量是0,那么sem_trywait函数立即返回错误EAGAIN。
1.16 #include <semaphore.h> |
信号量释放操作。相当于 原语V |
int sem_post(sem_t * sem); |
返回: 如果成功0, 失败设置 Exxx 到 error |
原子性的增加由sem指向的信号量计数。这个函数不会被阻塞。
1.17 #include <semaphore.h> |
获得信号量 |
int sem_getvalue(sem_t * sem, int * sval); |
返回: 如果成功0, 失败设置 Exxx 到 error |
获得sem指向的信号量的指到sval中。
1.18 #include <semaphore.h> |
信号量销毁函数 |
int sem_destroy(sem_t * sem); |
返回: 如果成功0, 失败设置 Exxx 到 error |
销毁一个信号量对象,释放他可能拥有的资源。在调用sem_destroy函数后没有线程可以再等待此信号量。在Linux线程实现中,没有资源于信号量相关联,因此sem_destroy事实上除了检查没有线程等待此信号量外什么也没作。
2) Example
/* File sem.c */
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#define MAXSTACK 100
int stack[MAXSTACK][2];
int size=0;
sem_t sem;
/* 从文件1.dat读取数据,每读一次,信号量加一*/
void ReadData1(void){
FILE *fp = fopen("1.dat","r");
while(!feof(fp)) {
fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]);
sem_post(&sem);
++size;
}
fclose(fp);
}
/*从文件2.dat读取数据*/
void ReadData2(void){
FILE *fp=fopen("2.dat","r");
while(!feof(fp)) {
fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]);
sem_post(&sem);
++size;
}
fclose(fp);
}
/*阻塞等待缓冲区有数据,读取数据后,释放空间,继续等待*/
void HandleData1(void){
while(1){
sem_wait(&sem);
printf("Plus:%d+%d=%d/n",stack[size][0],stack[size][1],
stack[size][0]+stack[size][1]);
--size;
}
}
void HandleData2(void){
while(1){
sem_wait(&sem);
printf("Multiply:%d*%d=%d/n",stack[size][0],stack[size][1],
stack[size][0]*stack[size][1]);
--size;
}
}
int main(void){
pthread_t t1,t2,t3,t4;
sem_init(&sem,0,0);
pthread_create(&t1,NULL,(void *)HandleData1,NULL);
pthread_create(&t2,NULL,(void *)HandleData2,NULL);
pthread_create(&t3,NULL,(void *)ReadData1,NULL);
pthread_create(&t4,NULL,(void *)ReadData2,NULL);
/* 防止程序过早退出,让它在此无限期等待*/
pthread_join(t1,NULL);
}