Unix环境多线程编程(三) [转]

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);
}

 

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值