Linux进程间通信——信号量

信号量

此处只涉及利用“二进制信号量”(只用0和1)完成“控制线程顺序”为中心的同步方法。

信号量的创建和销毁函数:

pshared参数超出我们关注的范围,默认向其传递0.

 

信号量相当于互斥量lock,unlock的函数:

 

调用sem_init函数时,操作系统将创建信号量对象,此对象中记录着“信号量值”整数。该值在调用sem_post函数时增1,调用sem_wait函数时减1。信号量的值不能小于0,当信号量为0的情况下调用sem_wait函数时,调用函数的线程将进入阻塞状态。此时如果有其它线程调用sem_post函数,信号量的值将变为1,而原来阻塞的线程可以将该信号量重新减为0并跳出阻塞状态。       

实际上就是通过这种特性完成临界区的同步操作,通过如下形式同步临界区:

[cpp]  view plain  copy
  1. sem_wait(&sem);             //信号量变为0...  
  2. //临界区的开始  
  3. //.........  
  4. //临界区的结束  
  5. sem_post(&sem);             //信号量变为1  

上述代码中,调用sem_wait函数进入临界区的线程在调用sem_post函数前不允许其它线程进入临界区。

信号量的值在0和1之间跳转,因此,具有这种特性的机制称为”二进制信号量“。

 

示例:线程A从输入得到值后存入全局变量num,此时线程B将取走该值并累加。该过程共进行5次,完成后输出总和并退出

[cpp]  view plain  copy
  1. /* 控制访问顺序的线程同步 */  
  2. #include<stdio.h>  
  3. #include<pthread.h>  
  4. #include<semaphore.h>  
  5.   
  6. void * read(void * arg);  
  7. void * accu(void * arg);  
  8. static sem_t sem_one;  
  9. static sem_t sem_two;  
  10. static int num;  
  11.   
  12. int main(int argc, char *argv[])  
  13. {  
  14.     pthread_t id_t1,id_t2;  
  15.     sem_init(&sem_one,0,0);     //sem_one初始值为0  
  16.     sem_init(&sem_two,0,1);     //sem_two初始值为1  
  17.   
  18.     pthread_create(&id_t1,NULL,read,NULL);  
  19.     pthread_create(&id_t2,NULL,accu,NULL);  
  20.   
  21.     pthread_join(id_t1,NULL);  
  22.     pthread_join(id_t2,NULL);  
  23.   
  24.     sem_destroy(&sem_one);  
  25.     sem_destroy(&sem_two);  
  26.     return 0;  
  27. }  
  28.   
  29. void * read(void * arg)  
  30. {  
  31.     int i;  
  32.     for(i=0; i<5; i++)  
  33.     {  
  34.         fputs("Input num: ",stdout);  
  35.   
  36.         sem_wait(&sem_two);     //初始值为1,调用sem_wait,sem_two变为0;    阻塞,在accu中加1后跳出阻塞状态  
  37.         scanf("%d",&num);  
  38.         sem_post(&sem_one);     //sem_one变为1  
  39.     }  
  40.     return NULL;  
  41. }  
  42.   
  43. void * accu(void * arg)  
  44. {  
  45.     int sum=0, i;  
  46.     for(i=0; i<5; i++)  
  47.     {  
  48.         sem_wait(&sem_one);     //sem_one变为0,阻塞,在read中加1后跳出阻塞状态  
  49.         sum+=num;  
  50.         sem_post(&sem_two);     //sem_two变为1  
  51.     }  
  52.     printf("Result: %d \n",sum);  
  53.     return NULL;  
  54. }  

15,16行生成两个信号量。掌握需要2个信号量的原因。

运行结果:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值