线程同步与互斥---信号量&读写锁

信号量
1、什么是信号量
为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题
信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,调协进程对共享资源的访问的。

信号量
是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作。最简单的信号量是只能取0和1的变量,这也是信号量最常见的一种形式,叫做二进制信号量。

2、信号量的工作原理

由于信号量只能进行两种操作等待和发送信号
P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.

信号量函数
1>初始化信号量

int sem_init(sem_t *sem, int pshared, unsigned int value);

2>操作信号量
P操作

    等待信号量:将信号量的值减1
int sem_wait(sem_t *sem);//信号量的P操作
int sem_trywait(sem_t *sem);//信号量的P操作(非阻塞版本)

V操作

     发布信号量:表示资源使用完毕,可用归还资源,将信号量的值加1
int sem_post(sem_t *sem);//信号量的V操作

销毁信号量

int sem_destroy(sem_t *sem);

基于环形队列的的生产者消费者模型

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

int ring[64];
sem_t blank_sem; //生产者关心的格子信号量
sem_t data_sem;   //消费者关心的数据信号量

void* producter(void* arg)  //生产者句柄
{
    int step=0;
    int data=0;
    while(1)
    {
        sleep(1);  
        sem_wait(&blank_sem); //等待信号量  格子数-1
        data=rand()%123;   
        ring[step]=data;  
        ++step;
        step%=64;
        printf("product done:%d\n",data);
        sem_post(&data_sem);//发布信号量 数据+1
    }
}

void* consumer(void* arg)  //消费者句柄
{
    int step=0;
    int data=0;
    while(1)
    {
        sem_wait(&data_sem); //等待信号量 数据-1
        data=ring[step];
        ++step;
        step%=64;
        printf("consumer done:%d\n",data);
        sem_post(&blank_sem); //发布信号量 数据+1
    }
}

int main()
{
    sem_init(&blank_sem,0,64);//格子信号量的初始化
    sem_init(&data_sem,0,0); //数据信号量的初始化

    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,producter,NULL);//生产者线程
    pthread_create(&tid2,NULL,consumer,NULL);//消费者线程

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    sem_destroy(&blank_sem);
    sem_destroy(&data_sem);
    return 0;
}

rwlock读写锁

读写锁概念:

编写多线程的时候,公共数据修改的机会比较少,相比较改写,他们读的机会反而高的多。在读的过程中,往往伴随着查找操作,中间耗时很长,给这种代码段加锁,会极大降低程序的效率
为解决上述问题,我们引入了读写锁的概念

读写锁:本质上是一种自旋锁

    把对共享资源的访问者分为读者与写者,读者只对共享资源进行读访问
    写者对共享资源进行写操作,这种锁相对自旋锁而言,能提高并发性,因为
    在多处理器系统中,它允许同时有多个读者来访问共享资源,

注意:一个读写锁同时只能有一个写者或者多个读者,不能同时既有读者又有写者

自旋锁:当申请锁资源的线程占用临界资源的时间比较短,一直询问不进行挂起的锁

读写锁的规则:
写者与写者:互斥
写者与读者:同步、互斥
读者与读者:没有关系

读写锁的接口

定义读写锁
            pthread_rwlock_t rwlock;
初始化读写锁 
            int pthread_rwlock_init

读写锁的操作

    int pthread_rwlock_rdlock(pthread_rwlock_t *rwptr);
    //以阻塞方式获取读出锁
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwptr);
    //以阻塞方式获取写入锁
    int pthread_rwlock_unlock(pthread_rwlock_t *rwptr);
    //释放读出锁或写入锁
    int pthread_rwlockattr_destroy //销毁读写锁

猜你喜欢

转载自blog.csdn.net/yu876876/article/details/81478735