Linux:线程同步之信号量

信号量

(1)What(什么是信号量)

提供一种计数器的方式控制对共享资源的访问;当计数器大于0时,请求资源成功并计数器-1;当计数器小于0时,线程阻塞,等待其它线程执行signal(V操作)唤醒它

(2)Why(信号量的作用)

  • 实现线程的同步与互斥:通过信号量的设计,可以实现对共享资源的串行访问
  • 实现线程的等待与通知机制:当信号量小于0时,当前线程将被阻塞;当信号量大于0时,会唤醒一个阻塞在信号量上的线程

(3)How(如何使用信号量实现线程同步)

step01:创建信号量

可以看作是创建一个信号量对象

sem_t sem; 

step02:初始化信号量

可以看作是对信号量对象的一个初始化,这一过程会给信号量的计数器赋予一个初始值

int sem_init(sem_t *sem, int pshared, unsigned int value); 
  • 参数sem:被初始化的信号量对象
  • 参数pshared:默认为0,表示信号量用于线程同步;其它表示信号量用于进程同步
  • 参数value:表示信号量的数量,常用用于表示共享资源的数量
  • 返回值:成功返回0,失败返回-1,并设置错误码

step03:请求资源

请求获取共享资源,此时信号量的计数器减1;如果信号量小于1,请求失败,线程阻塞,直到信号量满足条件时解除阻塞

int sem_wait(sem_t *sem); 
  • 参数sem:请求共享资源,如果sem中的计数器大于0,则请求成功,否则线程阻塞
  • 返回值:成功返回0,失败返回-1,并设置错误码

step04:释放资源

释放共享资源,此时信号量的计数器加1,此时会唤醒一个等待该共享资源的线程

int sem_post(sem_t *sem);

  • 参数sem:释放共享资源,sem中的计数器+1
  • 返回值:成功返回0,失败返回-1,并设置错误码
    step05:销毁信号量

本质就是释放信号量对象的内存空间

int sem_destroy(sem_t *sem); 
  • 参数sem:将要被销毁的信号量对象
  • 返回值:成功返回0,失败返回-1,并设置错误码

(4)代码实例

以下代码是对共享资源的互斥访问,共享资源的个数为5

#include <semaphore.h>
#include <unistd.h>
#include <iostream>
#include <pthread.h>
using namespace std;
pthread_mutex_t mutex;
sem_t semProc;
sem_t semComu;
struct Node{
	int iVal;
	Node * ptrNext;
	static int iSize;
};
int Node::iSize = 0;
Node * head = NULL;
void *produce(void  *arg){
	int i = 0;
	while(1){
		sem_wait(&semProc);
		pthread_mutex_lock(&mutex);
		int iVal = i;
		Node *node = new Node;
		node->iVal = iVal;
		node->ptrNext = head->ptrNext;
		head->ptrNext = node;
		Node::iSize++;
		cout<<"Producing "<<iVal<<"("<<Node::iSize<<")"<<endl;
		pthread_mutex_unlock(&mutex);
		sem_post(&semComu);
		++i;
		sleep(1);
	}
}
void *consume(void *arg){
	while(1){
		sem_wait(&semComu);
		pthread_mutex_lock(&mutex);
		if(head->ptrNext!=NULL)
		{
			cout<<"Comsuing "<<head->ptrNext->iVal;
			Node *ptr = head->ptrNext;
			head->ptrNext = ptr->ptrNext;
			Node::iSize--;
			delete ptr;
			cout<<"("<<Node::iSize<<")"<<endl;
			ptr = 0;
		}
		pthread_mutex_unlock(&mutex);
		sem_post(&semProc);
		sleep(2);return NULL; 
}
int main()
{
	head = new Node; 
	pthread_t tidProc,  tidComu; 
	sem_init(&semProc, 0, 5); 
	sem_init(&semComu, 0, 0); 
	pthread_create(&tidProc,  NULL,  produce,  NULL); 
	pthread_create(&tidComu, NULL, conmuse, NULL); 
	pthread_join(tidProc, NULL); 
	pthread_join(tidComu, NULL); 
	return 0; 
}
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值