首页 > 编程学习 > Linux之posix信号量

Linux之posix信号量

发布时间:2022/10/5 17:34:15

今天来讲下POSIX信号量,用于同步操作,达到无冲突的访问共享资源的目的,可以用于线程间同步。

信号量就是一个计数器+等待队列+等待+唤醒

1.信号量的基本接口

1)初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem:信号量变量
pshared:0表示线程间共享,非0表示进程间共享(决定用于线程间还是进程间)
value:信号量初始值

2)销毁信号量
int sem_destroy(sem_t *sem);

3)等待信号量
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);

4)发布信号量
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。 int sem_post(sem_t *sem);

信号量和条件变量的区别:
信号量与条件变量的区别:信号量拥有资源计数的功能,临界资源是否能够操作通过自身技术判断,条件变量是搭配互斥锁一起使用的,信号量还可以实现互斥,计数仅为0/1< font>

2.信号量实现生产者与消费者模型

上一节我用基本队列实现了一个生产者与消费者模型,这节我将用信号量和大小固定的环形
队列再次实现生产者与消费者模型:

实现代码

  1 #include<iostream>2 #include<pthread.h>3 #include<vector>4 #include<semaphore.h>5 6 //实现线程安全的环形队列,用信号量和线性表实现7 //信号量就是一个计数器,具有等待队列+等待+唤醒功能8 9 class RingQueue10 {11 public:12     RingQueue(int cap = 10):queue(10),capacity(cap)      //构造函数,采用了初始化列表的形式,定义环形队列大小capacity为1013             ,write_step(0),read_step(0){14         //int sem_init(sem_t *sem, int pshared, unsigned int value);15         //sem:信号量变量16         //pshared:决定信号量用于线程还是进程17         //0为线程   !0为进程18         //value:信号量初始计数19         sem_init(&data,0,0);20         sem_init(&idle,0,cap);21         sem_init(&lock,0,1);22     }23     ~RingQueue(){                         //析构函数24         sem_destroy(&data);25         sem_destroy(&idle);26         sem_destroy(&lock);27     }28     bool QueuePush(int data){29         ProductorWait();                  //因为信号量自带一个计数功能,所以不需要在循环判断,先加一个等待是为了判断是否队列空了,如果先加锁然后却发现满了程序就会卡在productorwait()那里没有解锁。30         QueueLock();                     //访问临界资源加锁31         queue[write_step] = data;        //放数据32         write_step = ((write_step)+1)%capacity;   //写指针要改变33         QueueUnlock();                   //访问完毕后解锁,因为锁只是限制临界资源的访问,不限制其他操作34         ConsumorWakeUp();                //唤醒消费者35         return true;36     }37     bool QueuePop(int *data){          38         ConsumorWait();      //同理先加一个等待是为了判断是否有资源可以取,否则先加锁了,结果发现没有临界资源可以访问,则会卡在consumorwait()那里没有解锁。39         QueueLock();40         *data = queue[read_step];               //取数据41         read_step = ((read_step)+1)%capacity;   //渎指针要改变42         QueueUnlock();43         ProductorWakeUp();44         return true;45     }46 private:47     void QueueLock(){48         sem_wait(&lock);49     }50     void QueueUnlock(){51         sem_post(&lock);52     }53     void ConsumorWait(){54         sem_wait(&data);55     }56     void ConsumorWakeUp(){57         sem_post(&data);58     }59     void ProductorWait(){60         sem_wait(&idle);61     }62     void ProductorWakeUp(){63         sem_post(&idle);64     }65 private:66     std::vector<int> queue;67     int capacity;68     int write_step;69     int read_step;70     sem_t data;   //代表消费者信号量    71     sem_t idle;   //代表生产者信号量72     sem_t lock;73 };74 75 void* pth_consumor(void* arg)76 {77     RingQueue *q = (RingQueue*) arg;78     while(1){79         int data;80         q->QueuePop(&data);81         std::cout<<"consumor get data!"<<std::endl;82     }83     return NULL;84 }85 86 void* pth_productor(void* arg)87 {88     RingQueue* q = (RingQueue*) arg;89     int i=0;90     while(1){91         q->QueuePush(i);92         std::cout<<"productor put data!"<<std::endl;93         i++;94     }95     return NULL;96 }97 98 int main()99 {
100     pthread_t ctid[4],ptid[4];
101     int ret,i;
102     RingQueue q;
103     for(i=0;i<4;i++){
104         ret = pthread_create(&ctid[i],NULL,pth_consumor,(void*)&q);
105         if(ret!=0){
106             std::cout<<"consumor not exist!"<<std::endl;
107             return -1;
108         }
109     }
110     for(i=0;i<4;i++){
111         ret = pthread_create(&ptid[i],NULL,pth_productor,(void*)&q);
112         if(ret!=0){
113             std::cout<<"productor not exist!"<<std::endl;
114             return -1;
115         }
116     }
117     for(i=0;i<4;i++){               //线程等待
118         pthread_join(ctid[i],NULL); 
119     }
120     for(i=0;i<4;i++){
121         pthread_join(ptid[i],NULL);
122     }
123     return 0;
124 }

本文链接:https://www.ngui.cc/el/1524709.html
Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000