国外自助建站,手机免费制作网站模板免费下载,做的高大上的网站,电商运营包括哪些方面#x1f57a;作者#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 #x1f618;欢迎关注#xff1a;#x1f44d;点赞#x1f64c;收藏✍️留言 #x1f3c7;码字不易#xff0c;你的#x1f44d;点赞#x1f64c;收藏❤️关注对我真的… 作者 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 欢迎关注点赞收藏✍️留言 码字不易你的点赞收藏❤️关注对我真的很重要有问题可在评论区提出感谢阅读 文章目录 前言1 POSIX信号量相关概念2 POSIX信号量相关函数3 基于环形队列的生产消费模型 前言
在多线程编程领域理解 POSIX 信号量的概念和相关函数是至关重要的。POSIX 信号量作为一种重要的同步原语可以帮助我们在多线程环境中实现线程之间的协调与同步从而确保数据的一致性和避免竞争条件的发生。
本篇博客旨在深入探讨 POSIX 信号量的基本概念和相关函数帮助读者全面理解这一关键的并发编程工具。通过本文的学习读者将能够掌握如何灵活地运用 POSIX 信号量来构建并发程序提高程序的性能和可靠性。让我们一起深入探索 POSIX 信号量的奥秘为多线程编程的世界增添新的智慧与力量。
1 POSIX信号量相关概念
POSIX信号量是什么 信号量的本质是一个计数器是用来描述临界资源有效的计数器 POSIX信号量和SystemV信号量作用相同都是用于同步操作达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。 当多个线程想要获取信号量的时候都会对信号量当中的资源计数器进行减一操作。 如果初始化信号量的资源计数器的值为1表示当前只有一个资源这就意味着只有一个线程在同一时刻可以获取到信号量。 如果想要实现线程同步初始化信号量的资源计数器的值就不必为1了它可以根据需要设置
如果大于0则表示还有多少资源可以使用等于0则表示没有资源可以使用小于0则表示有多少线程在等待资源。
2 POSIX信号量相关函数
信号量初始化
#include semaphore.h
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数sem_t: 信号量的类型sem: 传入待要初始化的信号量pshared: 0 表示线程间共享非0表示进程间共享value信号量初始值信号量销毁
int sem_destroy(sem_t *sem);
参数sem:待销毁的信号量信号量等待
功能等待信号量会将信号量的值减1int sem_wait(sem_t *sem); //P()信号量发布
功能发布信号量表示资源使用完毕可以归还资源了。将信号量值加1。int sem_post(sem_t *sem);//V()3 基于环形队列的生产消费模型
上一个生产者-消费者的例子是基于queue的,其空间可以动态分配,现在基于固定大小的环形队列重写这个程序POSIX信号量。 环形结构起始状态和结束状态都是一样的不好判断为空或者为满所以可以通过加计数器或者标记位来判断满或者空。另外也可以预留一个空的位置作为满的状态 但是我们现在有信号量这个计数器就很简单的进行多线程间的同步过程 实现代码如下 RingQueue.cc
#pragma#includeiostream
#includeunistd.h
#includevector
#includesemaphore.h
#includestdlib.h#define NUM 10class RingQueue
{
private:std::vectorint v;int _cap;//容量sem_t sem_product;//生产者sem_t sem_consume;//消费者int p_index;//生产者索引int c_index;//消费者索引public:RingQueue(int capNUM):_cap(cap),v(cap){sem_init(sem_product,0,cap);sem_init(sem_consume,0,0);p_index 0;c_index 0;}~RingQueue(){sem_destroy(sem_product);sem_destroy(sem_consume);}void put(const intin){sem_wait(sem_product);v[p_index] in;p_index;p_index p_index%NUM;sem_post(sem_consume);}void get(int out){sem_wait(sem_consume);out v[c_index];c_index;c_index c_index%NUM;sem_post(sem_product);}
};main.cc
#includeRingQueue.cc
using namespace std;void* Consumer(void* arg){RingQueue *bq (RingQueue*)arg;int data;while(1){bq-get(data);coutI am pthread_self() is consumer : dataendl;}
}void* Product(void* arg){RingQueue* bq (RingQueue*)arg;srand((unsigned int)time(NULL));while(1){int data rand()%100;bq-put(data);coutI am pthread_self() is product dataendl;sleep(1);}
}int main()
{RingQueue* pq new RingQueue();pthread_t c;pthread_t p;pthread_create(c,NULL,Consumer,(void*)pq);pthread_create(p,NULL,Product,(void*)pq);pthread_join(c,NULL);pthread_join(p,NULL);return 0;
}makefile
main:main.ccg -o $ $^ -lpthread
.PHONY:
clean:rm -f main结果 可以观察到生产一个消费一个