20220921(信号量)

信号量,是是相对折中的一种处理方式,既保证同步,数据不混乱,又能提高线程发送。

由于互斥锁的粒度比较大,如果我们希望在多个线程间对某以对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。这样虽然达到了多线程操作共享数据时保证数据正确性的目的,却无形中导致线程的并发性下降。线程从并行执行,变成了串行执行。与直接使用单进程无异。

主要函数

sem_init:函数(初始化信号量)

sem_destroy:函数(销毁信号量)

sem_wait:函数(信号量减减操作(类似加锁))

sem_trywait:函数(尝试对信号量加锁)

sem_timewait:函数(限时尝试对信号量加锁)

sem_post:函数(信号量加加操作(类似解锁))

以上6个函数的返回值都是:成功返回0,失败返回-1,同时设置(errno。(注意:他们没有pthread前缀))。

sem_t类型,本质仍是结构体。但应用期间可简单看作为整数,忽略显示细节(类型于使用文件描述符)。

sem_tsem:规定信号量sem不能<0,头文件<semaphore.h>

信号量基本操作

sem_wait:

1.信号量大于0,则信号量--

2.信号量等于0,再次调用会造成线程阻塞。

sem_post:

将信号量++,同时唤醒阻塞在信号量上的线程,由于sem的实现对用户隐藏,所以所谓的++、--操作只能通过函数来实现,而不能直接++、--符号

信号量的初值,决定了占用信号量的线程的个数。

一个生产者,两个消费者测试(参考下图)

 代码如下:

#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>


#define NUM 5

int queue[NUM];//全局数组实现环形队列
//用sem_t类型,定义了2个信号量变量
sem_t blank_number, product_number ;//空格子信号量,产品信号量

void *producer(void *arg)
{
	sleep(10);
	int i=0;
	while (1) 
	{
		sem_wait(&blank_number);//生产者将空格子数-- ,为0则阻塞等待
		queue[i] = rand() % 1000 + 1;//生产一个产品
		printf("i=%d----Produce---%d\n",i,queue[i]); 
		sem_post(&product_number);//将产品数++
		
		i=(i+1)%NUM;//借助下标实现环形
	//	sleep( rand()%1);
		sleep(1);
	}
}
void *consumer02(void *arg)
{
	int i=1;
	
	sleep(1);
	while (1) 
	{
		sleep(5);
		sem_wait(&product_number);//消费者将产品数--,为则阻塞等待
		printf("i=%d----Consume---%d\n" ,i, queue[i]);
		queue[i] = 0;//消费一个产品
		sem_post(&blank_number);//消费掉以后,将空格子数++
		
		i = (i+2) % NUM;
	//	sleep(rand( )%3);
	}
}

void *consumer(void *arg)
{
	int i=0;
	
	sleep(1);
	while (1) 
	{
		sleep(5);
		sem_wait(&product_number);//消费者将产品数--,为则阻塞等待
		printf("i=%d----Consume---%d\n" ,i, queue[i]);
		queue[i] = 0;//消费一个产品
		sem_post(&blank_number);//消费掉以后,将空格子数++
		
		i = (i+2) % NUM;
	//	sleep(rand( )%3);
	}
}



int main(int argc, char *argv[])
{
	pthread_t pid, cid[2];
	sem_init(&blank_number, 0, NUM); //初始化线程间共享-0,空格子信号量为5,
	sem_init(&product_number, 0,0);//初始化线程间共享-0,产品数为0
	
	pthread_create(&pid, NULL, producer, NULL);
	pthread_create(&cid[0], NULL, consumer, NULL);
	pthread_create(&cid[1], NULL, consumer02, NULL);
	
	pthread_join(pid, NULL);
	pthread_join(cid[0], NULL);
	pthread_join(cid[1], NULL);
	
	sem_destroy(&blank_number );
	sem_destroy(&product_number);
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值