Linux多线程——使用信号量同步线程

一、信号量的概念
线程间和进程间通信中使用的信号量的概念是一样的,它是一种特殊的变量,可以被增加或者减少,但对其的关键访问是原子操作。如果一个程序中有多个线程试图改变一个信号量的值,系统将保证所有的操作都依次进行。
二、信号量的接口函数
信号量的函数都以sem_开头,线程中使用的基本信号量函数有4个,它们都声明在头文件semaphore.h中。
sem_init函数
该函数用于创建信号量,其原型如下:

int sem_init(sem_t *sem,int pshared,unsigned int value);

该函数初始化由sem指向的信号对象,设置它的共享选项,并给它一个初始的整数值。
pshared控制信号量的类型,如果其值为0,就表示这个信号量是当前进程的局部信号量,否则信号量就可以在多个进程之间共享,value为sem的初始值。调用成功时返回0,失败返回-1.

sem_wait函数
该函数用于以原子操作的方式将信号量的值减1。原子操作就是,如果两个线程企图同时给一个信号量加1或减1,它们之间不会互相干扰。它的原型如下:

int sem_wait(sem_t *sem);  

sem指向的对象是由sem_init调用初始化的信号量。调用成功时返回0,失败返回-1.
sem_post函数
该函数用于以原子操作的方式将信号量的值加1。它的原型如下:

int sem_post(sem_t *sem);  

与sem_wait一样,sem指向的对象是由sem_init调用初始化的信号量。调用成功时返回0,失败返回-1.
sem_destroy函数
该函数用于对用完的信号量的清理。它的原型如下:

int sem_destroy(sem_t *sem); 

三、信号量的函数使用
代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
  sem_t sem;
  
  void thread_fun1(void* arg)
  {
  	  printf("thread func1\n");
      sem_wait(&sem);
      printf("thread_func1 running1\n");
  }
  void thread_func2(void* arg)
  {
      printf("thread_func2 running\n");
      sem_post(&sem);
  }
  int main()
  {
      sem_init(&sem,0,0);
      pthread_t thread[2];
      pthread_create(&(thread[0]),NULL,(void*)thread_fun1,NULL);
      printf("main thread running\n");
      sleep(10);
      pthread_create(&(thread[1]),NULL,(void*)thread_fun2,NULL);
      printf("main thread running2\n");
      pthread_join(thread[0],NULL);
      pthread_join(thread[1],NULL);
      sem_destroy(&sem);
      return 0;
  }

程序的执行过程:
(1)首先创建信号量,第二个参数为0,表示这个信号量是当前进程的局部信号量,用于当前进程内线程之间的信号同步,且初始值为0,所以调用sem_wait()的线程需阻塞等待信号量的值大于1时才有机会继续执行。
(2)然后使用pthread_create()函数创建两个线程。
(3)线程1创建完成后,由于信号量初始化value=0,调用sem_wait会阻塞这个线程,信号量的值将减少1(此时<0),这个线程函数就会等待。
(4)主线程sleep(10)后,线程2创建并执行调用,sem_post用于使信号量的值增加1,此时线程1可以执行。
主线程使用pthread_join等待所创建的两个线程的结束。

工作中使用场景:
(1)用于响应TCP连接的服务器,单独创建一个线程用于响应TCP连接的请求,线程执行体的执行使用信号量来控制,等待有TCP响应数据过来时再执行线程执行体;
(2)主线程用于封装响应TCP连接的数据,数据封装完成放入到待发送队列,然后使用信号量通知TCP响应的线程处理待发送队列;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值