zoukankan      html  css  js  c++  java
  • inux c编程:读写锁

    前面介绍的互斥量加锁要么是锁状态,要么就是不加锁状态。而且只有一次只有一个线程可以对其加锁。这样的目的是为了防止变量被不同的线程修改。但是如果有线程只是想读而不会去写的话,这有不会导致变量被修改。但是如果是互斥量加锁,则读写都没有办法。这种场景不能使用互斥量,必须使用读写锁。

    读写锁可以有3种状态:

    1 读模式下加锁状态

    2 写模式下加锁状态

    3 不加锁状态

    一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权。但是任何希望以写模式对此锁进行加锁的线程都会阻塞。直到所有的线程释放它们的读锁为止。

    读写锁非常适合于对数据结构读的次数大于写的情况。当读写锁在写模式下时,它所保护的数据结构就可以被安全地修改,因为一次只有一个线程可以在写模式下拥有这个锁。

    读写锁也叫做共享互斥锁。当读写锁是读模式锁住的,就可以说是以共享模式锁住的。当它是写模式锁住的时候,就可以说成是以互斥模式锁住的。

    #include <pthread.h>

    Int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

    Int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

    读写锁通过调用pthread_rwlock_init进行初始化。在释放读写锁占有的内存之前,需要调用pthread_rwlock_destroy做清理工作。如果pthread_rwlock_init为读写锁分配了资源,pthread_rwlock_destroy将释放这些资源。如果在调用pthread_rwlock_destroy之前就释放了读写锁占用的内存空间。那么分配给这个锁的资源就会丢失。

    要在读模式下锁定读写锁,需要调用pthread_rwlock_rdlock,要在写模式下锁定读写锁,需要调用pthread_rwlock_wrlock。不管以何种方式锁住读写锁。都可以调用pthread_rwlock_unlock进行解锁。

    #include <pthread.h>

    Int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

    Int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

    Int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

    来看一个基本的实现例子:

    pthread_rwlock_t rwlock;

    int data=1;

    void readerA(){

        while(1){

            pthread_rwlock_rdlock(&rwlock);

            printf("A读者读出:%d ",data);

            pthread_rwlock_unlock(&rwlock);

            Sleep(1000);

        }

    }

    void writerB(){

        while(1){

            pthread_rwlock_wrlock(&rwlock);

            data++;

            printf("B作者写入:%d ",data);

            pthread_rwlock_unlock(&rwlock);

            Sleep(1000);

        }

    }

    int main()

    {

        pthread_t t1;

        pthread_t t2;

        pthread_rwlock_init(&rwlock,NULL);

        pthread_create(&t1,NULL,readerA,NULL);

        pthread_create(&t2,NULL,writerB,NULL);

        pthread_join(t1,NULL);

        pthread_join(t2,NULL);

        pthread_rwlock_destroy(&rwlock);

        return 0;

    }

    运行结果如下:可以看到读者A在读取数据的时候,data能够保持原子性。不会被写的操作给抢占而导致数据不一致。

  • 相关阅读:
    紫色飞猪的研发之旅--07client-go实现进入pod模拟终端登录
    紫色飞猪的研发之旅--06go自定义状态码
    紫色飞猪的研发之旅--05go封装http请求
    紫色飞猪的研发之旅--04client-go客户端
    紫色飞猪的研发之旅--03golang:获取cookie
    支持remote write和exemplar的prometheus服务
    从头编写一个时序数据库
    解析Prometheus PromQL
    老板:把系统从单体架构升级到集群架构!
    小白自制Linux开发板 三. Linux内核与文件系统移植
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/9384258.html
Copyright © 2011-2022 走看看