一.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.小案例