【Linux】POSIX信号量与读写锁

一.POSIX信号量

1.基本概念

POSIX信号量和SystemV信号量作用相同,都是用来实现同步或互斥机制,本质也是计数器,通常用它来保护的临界资源的资源数目,但POSIX可以用于线程间同步

2.相关接口

初始化信号量

  •  #include <semaphore.h>
  • int  sem_init(sem_t  *sem,  int  pshared,  unsigned  int  value);
  • 第二个参数0表示线程间共享,非0表示进程间共享,第三个参数为信号量初始值

等待信号量(p操作)

  • int  sem_wait(sem_t  *sem)
  • 等待信号量。会将信号量值减1

发布信号量(v操作)

  • int  sem_post(sem_t *sem)
  • 发布信号量,表示资源使用完毕,可以归还资源,将信号量值加1

销毁信号量

  • int  sem_destroy(sem_t  *sem)

3.小案例

上次生产者--消费者的例子是基于链表的,这次基于环形队列,实现以下功能:如果队列满了,保证消费者先运行,这次可以将队列的空间和数据看做是两份不同的资源,而生产者只关心有没有空资源,消费者关心有没有数据资源,所以这里就需要有两个信号量来表示两份不同的资源,semBlank表示空资源,semData表示数据资源,初始值设为0

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

//队列最大容量
#define M 5

//队列
int ring[M];

//信号量
sem_t semBlank;//空资源
sem_t semData;//数据资源

//生产者
void *producer(void *arg)
{
	int i=0;
	while(1){
		//保证数据在1-100内
		int data=rand()%100+1;
		
		//生产前先P(semBlank)
		sem_wait(&semBlank);
		//生产
		ring[i]=data;
		printf("i am producer ,i product data is %d\n",data);
		//保证数组不会越界
		i++;
		i%=M;

		//生产完后,就会多一个数据资源
		sem_post(&semData);
		sleep(1);
	}
}

//消费者
void *consumer(void *arg)
{
	int i=0;
	while(1){
		//消费前先看有没有数据资源V(semData)
		sem_wait(&semData);
		//消费
		int data=ring[i];
		i++;
		i%=M;
		printf("i am consumer , a consume data is %d\n",data);
	
		//消费完,多一个空资源
		sem_post(&semBlank);
	}
}

int main()
{
	pthread_t tid1,tid2;
	srand((unsigned int)time(NULL));
	
	//初始化信号量
	sem_init(&semBlank,0,M);
	sem_init(&semData,0,0);

	//创建生产者消费者模型
	pthread_create(&tid1,NULL,producer,NULL);
	pthread_create(&tid2,NULL,consumer,NULL);
		
	//线程等待
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);

	sem_destroy(&semBlank);
	sem_destroy(&semData);
	return 0;
}

二.读写锁

1.基本概念

有种情况是非常常见的,就是对于公共数据修改的机会非常少,相比较改写,它们读的机会反而更多,读写锁本质是一种自旋锁(之前的互斥锁属于挂起等待锁)

2.自旋锁与挂起等待锁

它们都是为实现保护共享资源而提出的一种锁机制,其锁与挂起等待锁比较类似,它们都是为了解决对某项资源的互斥机制使用,无论是挂起等待锁还是自旋锁,在任何时刻最多有一个执行单元获得锁。但是两者在调度机制上有所不同。对于挂起等待锁,如果资源已经被占用,资源申请者只能进入睡眠状态,如果自旋锁已经被别的执行单元占用,调用者就一直循环在那里看是否该自旋锁的保持着已经释放了锁,‘自旋’也由此而来

注意;写独占,读共享,写锁优先级高

3.相关接口

初始化:

  • int  pthread_rwlock_init(pthread_rwlock_t  *restrict  rwlock,  const  pthread_rwlockattr_t  *restrict  attr)

读者写者锁:

  • int  pthread_rwlock_rdlock(pthread_rwlock_t  *rwlock);
  • int  pthread_rwlock_wrlock(pthread_rwlock_t  *rwlock)

解锁:

  • int  pthread_rwlock_unlock(pthread_rwlock_t  *rwlock);

销毁:

  • int  pthread_rwlock_destroy(pthread_rwlock_t  *rwlock)

4.小案例

猜你喜欢

转载自blog.csdn.net/lw__sunshine/article/details/81144804