首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux共享内存读写锁

在Linux系统中,共享内存是一种高效的进程间通信(IPC)机制,允许多个进程访问同一块物理内存区域。为了保证数据的一致性和完整性,在共享内存的并发访问中常常会用到读写锁。

一、基础概念

  1. 共享内存:多个进程可以访问同一块内存区域,这块内存区域独立于进程的地址空间。
  2. 读写锁(Read - Write Lock)
    • 允许多个进程同时读取共享资源,但在有进程写入时,其他进程不能进行读写操作。
    • 当一个进程获取写锁时,它独占对共享资源的访问权,直到释放写锁。
    • 当一个进程获取读锁时,其他进程也可以获取读锁,但如果有一个进程获取了写锁,新的读锁请求将被阻塞。

二、优势

  1. 提高并发性能
    • 对于读多写少的场景,允许多个进程同时读取共享内存中的数据,大大提高了并发效率。
  • 数据一致性
    • 写锁确保了在写入数据时不会有其他进程干扰,保证了数据的正确性。

三、类型

  1. 基于内核的读写锁(如Linux中的rwlock
    • 由操作系统内核管理,适用于跨进程的同步需求。
    • 优点是可靠性高,缺点是可能涉及较多的系统调用开销。
  • 用户空间的读写锁实现
    • 可以通过一些库函数或者自定义算法在用户空间实现读写锁。
    • 优点是避免了内核态和用户态切换的开销,但需要开发者自己处理一些复杂的同步逻辑。

四、应用场景

  1. 缓存系统
    • 多个进程可能需要读取共享的缓存数据,而只有少数进程可能会更新缓存。使用读写锁可以提高缓存的并发访问效率。
  • 配置管理
    • 多个进程可能同时读取系统配置信息,但只有管理员进程或特定进程能够修改配置。读写锁可以保证配置的一致性。

五、可能遇到的问题及解决方法

  1. 死锁
    • 原因:如果进程获取读锁后试图获取写锁,而此时另一个进程已经获取了写锁,就可能导致死锁。
    • 解决方法:采用合理的锁获取顺序,例如先尝试获取写锁,如果获取失败再尝试获取读锁;或者设置锁的超时时间,超时后自动释放锁并重新尝试。
    • 示例代码(使用pthread_rwlock库函数,这是Linux下常用的读写锁实现方式):
代码语言:txt
复制
#include <pthread.h>
#include <stdio.h>

pthread_rwlock_t rwlock;

void* reader(void* arg) {
    pthread_rwlock_rdlock(&rwlock);
    // 读取共享内存数据操作
    printf("Reading data...
");
    pthread_rwlock_unlock(&rwlock);
    return NULL;
}

void* writer(void* arg) {
    pthread_rwlock_wrlock(&rwlock);
    // 写入共享内存数据操作
    printf("Writing data...
");
    pthread_rwlock_unlock(&rwlock);
    return NULL;
}

int main() {
    pthread_rwlock_init(&rwlock, NULL);
    pthread_t reader_thread, writer_thread;
    pthread_create(&reader_thread, NULL, reader, NULL);
    pthread_create(&writer_thread, NULL, writer, NULL);
    pthread_join(reader_thread, NULL);
    pthread_join(writer_thread, NULL);
    pthread_rwlock_destroy(&rwlock);
    return 0;
}
  1. 饥饿现象
    • 原因:如果读进程频繁获取读锁,写进程可能长时间无法获取写锁。
    • 解决方法:可以采用一些公平性策略,例如按照请求锁的顺序分配锁,或者设置读锁的最大持有数量等。
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

linux读写锁_共享内存读写锁

一、读写锁是什么?...读写锁其实还是一种锁,是给一段临界区代码加锁,但是此加锁是在进行写操作的时候才会互斥,而在进行读的时候是可以共享的进行访问临界区的 ps:读写锁本质上是一种自旋锁 二、为什么需要读写锁?...而读的机会却是非常多的,此公共数据的操作基本都是读,如果每次操作都给此段代码加锁,太浪费时间了而且也很浪费资源,降低程序的效率,因为读操作不会修改数据,只是做一些查询,所以在读的时候不用给此段代码加锁,可以共享的访问...,只有涉及到写的时候,互斥的访问就好了 三、读写锁的行为 读写之间是互斥的—–>读的时候写阻塞,写的时候读阻塞,而且读和写在竞争锁的时候,写会优先得到锁 四、自旋锁&挂起等待是锁?...:效率不高,很可能会使临界区的代码不被任何线程执行,因为可能会是线程被 CPU调度走了但是却没有被调度回来 五、读写锁是怎么实现?

6.2K11

linux读写锁

读写锁 与互斥量类似,但读写锁允许更高的并行性。其特性为:写独占,读共享。 读写锁状态: 一把读写锁具备三种状态: 1. 读模式下加锁状态 (读锁) 2. 写模式下加锁状态 (写锁) 3....不加锁状态 读写锁特性: 1. 读写锁是“写模式加锁”时, 解锁前,所有对该锁加锁的线程都会被阻塞。 2....那么读写锁会阻塞随后的读模式锁请求。优先满足写模式锁。读锁、写锁并行阻塞,写锁优先级高 读写锁也叫共享-独占锁。当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。...写独占、读共享。 读写锁非常适合于对数据结构读的次数远大于写的情况。...函数 以读方式请求读写锁。

3.3K30
  • 【Linux】:多线程(读写锁 && 自旋锁)

    读写锁 1.1 基本概念 读写锁(Read-Write Lock)是一种用于多线程环境下同步访问共享资源的锁。它与传统的互斥锁(Mutex)有所不同,提供了更细粒度的控制,以便提高并发性能。...,不允许多个线程同时获得写锁,并且写操作和读操作也是互斥的 读写锁的特点: 读读不互斥:多个读线程可以同时访问共享资源 读写互斥:读操作和写操作互斥,即在写操作进行时,其他线程不能进行读或写操作 写写互斥...:多个写线程不能同时进行写操作 具体来说,读写锁的行为如下: 读操作(共享锁): 如果没有线程正在持有写锁,那么多个线程可以同时获得读锁并执行读取操作。...当读操作远多于写操作时,读写锁可以允许多个读线程同时访问共享资源,从而提高并发性能。...,形成活锁 使用场景: 短暂等待的情况:适用于锁被占用时间很短的场景,如多线程对共享数据进行简单的读写操作。

    17510

    【Linux】多线程(自旋锁、读写锁)

    今日更新了Linux线程的内容 欢迎大家关注点赞收藏⭐️留言 自旋锁 概述 自旋锁是一种多线程同步机制,用于保护共享资源免受并发访问的影响。...原理 自旋锁通常使用一个共享的标志位(如一个布尔值)来表示锁的状态。当标志位为 true 时,表示锁已被某个线程占用;当标志位为 false 时,表示锁可用。...使用场景 短暂等待的情况:适用于锁被占用时间很短很短的场景,如多线程对共享数据进行简单的读写操作 多线程锁使用:通常用于系统底层,同步多个cpu对共享资源的访问。...Linux提供的自旋锁系统调用 int pthread_spin_lock(pthread_spinlock_t *lock); int pthread_spin_trylock(pthread_spinlock_t...有,那就是读写锁。 注意:写独占,读共享,读锁优先级高 读者和读者是并发关系,写者和写者是互斥,读者和写者是互斥&&同步。 pthread库里面给我们提供了读写锁。

    13510

    Linux内核中的各种锁:信号量互斥锁读写锁原子锁自旋锁内存屏障等

    使用实例如下: #include linux/spinlock.h> // 定义自旋锁 spinlock_t my_lock; void my_function(void) { spin_lock...要注意:信号量本身也是个共享资源,它的++操作(释放资源)和--操作(获取资源)也需要保护。其实就是用的自旋锁保护的。...(2)))){ // do something } else{ // 没抢到 std::cout锁失败"; } 三、读写锁/抢占 — —临界区 读写锁: 用于读操作比写操作更频繁的场景,...它允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。这可以提高并发性能,因为读操作通常比写操作频繁得多。读写锁这种就属于高阶锁了,它的实现就可以用自旋锁。...所以RCU机制的核心有两个:1)复制后更新;2)延迟回收内存 有RCU机制的话,读写就不需要做同步,也不会发生读写竞争了,因为读者是对原来的数据进行读,而写者是对拷贝出来的那份内存进行修改,读写可以并行

    1.6K20

    初识Linux · 共享内存

    我们通过这个图,引出我们今日的话题: 在Linux中,万物皆是文件的概念已经深深的刻入到了我们的大脑里面,在文件系统里面我们介绍了进程,介绍了地址空间,介绍了页表,介绍了物理内存之间的映射关系,知道了代码和数据的地址通过页表...在Linux源码里面是有共享内存对应的结构体的,这里因为不介绍,所以不放出对应的源码了,肯定就有人说了,怎么又又又是结构体?...因为Linux就是C语言写的呀,并且,C语言想要对某个对象管理,结构体不是最好的选择吗? 所以我们得出一个结论,共享内存 = 共享内存的数据 + 共享内存的属性!!...对于第一种模式,IPC_CREAT,代表的是如果创建的共享内存不存在,就创建,如果存在共享内存,就获取该共享内存并返回,说白了就是总能够获取一个共享内存,但是不一定是全新的。...例如,它可以指定是否允许共享内存区域在调用进程的地址空间中固定位置,或者是否允许读写访问等 那么为了获得地址,我们在类的私有成员变量里面新增一个_addrshm。

    8610

    共享内存无锁队列的实现

    作者:范健 导语: 共享内存无锁队列是老调重弹了,相关的实现网上都能找到很多。但看了公司内外的很多实现,都有不少的问题,于是自己做了重新实现。...主要是考虑了一些异常情况加强健壮性,并且考虑了C++11的内存模型。 为什么需要共享内存无锁队列?...又因为业务模块可能是多线程模式也可能是多进程模式,所以队列应该是在共享内存中。 简单的做法是,对队列的读写都加锁,但这样无疑会导致高并发下性能瓶颈就在这把锁上。所以我们需要无锁队列。...共享内存 另外一个值得一提的点是,共享内存我使用mmap,而非shmget。因为担心一台机器上部署的程序太多,可能出现共享内存key冲突的情况。...使用共享内存等共享资源时,更要想到,这资源不是我独占的,万一被有意或无意的篡改了数据该怎么办?能否尽量避免被别人篡改?如果被篡改,是否有发现和恢复机制?

    12.3K31

    【Linux】system V 共享内存

    可以,其他进程也可以通信 所以在任何时刻,可能有多个共享内存在被使用 系统中一定会存在很多共享内存同时存在 操作系统要不要整体管理所有的共享内存呢?要 操作性系统如何管理多个共享内存呢?...先描述,在组织 并不是在内存中开辟空间即可,系统为了管理共享内存,构建对应的描述共享内存的结构体对象 共享内存=共享内存的内核数据结构(伪代码:struct shm)+真正开辟的内存空间 2....创建共享内存 获取共享内存 创建共享内存,调用shmget函数,通过两个选项 若共享内存不存在则创建,若存在则报错 而获取共享内存,调用shmget函数,则返回已有的共享内存 ---- 此时运行可执行程序...将自己和共享内存关联起来 输入 man shmat 指令 at代表 关联 将共享内存和目标值关联起来 返回值为 共享内存的虚拟地址的起始地址 我们不知道应该把共享内存放在虚拟空间的什么地址处...,所以shmaddr设为NULL让系统自主去选择 shmflg 可以设置为 SHM_RDONLY 表示当前共享内存是只读的 一般设为0,默认为读写的 ---- 4.

    25320

    Linux进程通信——共享内存

    所以:共享内存 = 物理内存快 + 共享内存的相关属性 OS管理的是对这个共享内存的数据结构对象做管理的。 那么在创建共享内存的时候,如何保证共享内存在OS中是唯一的呢?答案就是key。...就像钥匙和锁一样。(fd与inode也是相同的道理) 那么如何查看IPC资源呢?...shmat 第一个参数是想和哪一个共享内存关联,第二个参数是想把这个共享内存映射到地址空间的哪个地方(不常用),第三个权限是读写权限(一般设置为0)。...void* attachshm(int shmid) { void* p = shmat(shmid, nullptr, 0); if((long long)p == -1L)//因为linux...void* attachshm(int shmid) { void* p = shmat(shmid, nullptr, 0); if((long long)p == -1L)//因为linux

    5.8K30

    Linux进程通信--共享内存

    首先由操作系统在物理内存中开辟一段内存空间,共享内存虽然是操作系统创建的,但是这些进程中的某一个需要来创建这个共享内存,这个共享内存属于操作系统的。...由此,操作系统就要对共享内存进程管理(先描述,再组织),共享内存不是简单的一段内存空间,也要有描述并管理共享内存的数据结构和匹配算法。简单来说,对共享内存的管理,就变成了对链表的增删查改。...总结一下: 共享内存=内存空间(数据)+共享内存的属性 共享内存的操作 创建共享内存函数接口 创建共享内存函数接口为:shmget #include #include 共享内存存不存在? 共享内存有自己对应的属性,这个属性有一个标识共享内存唯一性的字段,因此对应的共享内存存不存在,可以看对应的唯一性标识符。...<<std::endl; } 共享内存优缺点 共享内存不提供对共享内存的任何保护机制,双方进程不会出现等待进程的现象,会造成数据不一致问题。

    11610

    Linux学习——浅谈读写锁的使用

    一、读写锁是什么? 读写锁其实还是一种锁,是给一段临界区代码加锁,但是此加锁是在进行写操作的时候才会互斥,而在进行读的时候是可以共享的进行访问临界区的。...当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 读写锁的使用规则: 只要没有写模式下的加锁,任意线程都可以进行读模式下的加锁; 只有读写锁处于不加锁状态时,才能进行写模式下的加锁...; 读写锁也称为共享-独占(shared-exclusive)锁,当读写锁以读模式加锁时,它是以共享模式锁住,当以写模式加锁时,它是以独占模式锁住。...读写锁非常适合读数据的频率远大于写数据的频率从的应用中。这样可以在任何时刻运行多个读线程并发的执行,给程序带来了更高的并发度。 ps:读写锁本质上是一种自旋锁 二、为什么需要读写锁?...,只有涉及到写的时候,互斥的访问就好了 三、读写锁的行为 读写之间是互斥的—–>读的时候写阻塞,写的时候读阻塞,而且读和写在竞争锁的时候,写会优先得到锁 四、自旋锁&挂起等待锁(互斥锁)?

    1.7K30

    Linux内核编程--内存映射和共享内存

    有了这样的映射,进程利用指针直接读写虚拟地址就可以完成对文件的读写操作。这样可以避免进行read/write函数操作。...进程可以直接操作磁盘文件,用内存读写代替 I/O读写 应用场景: 1.进程间通信 使用内存映射实现进程间通信的两个场景: 场景1.有亲缘关系的进程间通信(父子进程) step1: 父进程创建内存映射区...2.文件读写操作 step1: 读磁盘文件,获得文件描述符 step2: 基于文件描述符建立进程的内存映射区 step3: 利用进程进行内存映射区的读写操作 step4: 释放内存映射区,关闭文件描述符...PROT_EXEC:映射区可执行 PROT_NONE:映射区不可访问 --flags参数取值: MAP_SHARED:变动是共享的,内存区域的读写影响到原文件 MAP_PRIVATE:变动是私有的,...内存区域的读写不会影响到原文件 返回:若成功,返回指向内存映射区域的指针,若出错,返回MAP_FAILED(-1)。

    6.2K10

    Linux内核30-读写自旋锁

    1 读/写自旋锁概念 自旋锁解决了多核系统在内核抢占模式下的数据共享问题。但是,这样的自旋锁一次只能一个内核控制路径使用,这严重影响了系统的并发性能。...根据我们以往的开发经验,大部分的程序都是读取共享的数据,并不更改;只有少数时候会修改数据。为此,Linux内核提出了读/写自旋锁的概念。...也就是说,没有内核控制路径修改共享数据的时候,多个内核控制路径可以同时读取它。如果有内核控制路径想要修改这个数据结构,它就请求读/写自旋锁的写自旋锁,独占访问这个资源。这大大提高了系统的并发性能。...通过上面的分析可以看出,读写自旋锁使用bit31表示写自旋锁,bit30-0表示读自旋锁,对于读自旋锁而言,绰绰有余了。...成员break_lock 对于另一个成员break_lock来说,同自旋锁数据结构中的成员一样,标志锁的状态。 rwlock_init宏初始化读写锁的lock成员。

    1.4K20

    【Linux修炼】16.共享内存

    进程之间通过共享内存进行关联 四.共享内存的特点 五.共享内存的内核结构 六.共享内存函数的总结 共享内存是为通信而诞生的。...,参数二:地址空间,一般设置为nullptr,参数三:读写权限,一般设置为0就可以了,默认就可以读写。...,因此还需要在createshm中添加选项: 接下来看看运行结果: 可以发现的是,由于我们新增了0600即拥有者的读写权限,perm也就显示了600,此外nattch的链接数量也变成了1,这说明有一个进程和这个共享内存关联起来了...也就是说,共享内存并不像管道一样,管道是当读写都打开时,如果不读,写满就会不写了,如果写端不写,读端就不会继续读了并且阻塞在那里,而共享内存没有做这样的保护。那么如何保护?...今后将会学到信号量和互斥锁的方式对管道进行保护。

    4K00

    无锁编程:c++11基于atomic实现共享读写锁(写优先)

    在多线程状态下,对一个对象的读写需要加锁,基于CAS指令的原子语句可以实现高效的线程间协调。...关于CAS的概念参见下面的文章: 无锁编程以及CAS 在c++11中CAS指令已经被封装成了 非常方便使用的atomic模板类, 详情参见: atomic参考 以下代码利用atomic实现了一个读写资源锁...,并且可以根据需要通过构造函数参数设置成写优先(write_first)(代码在gcc5和vs2015下编译通过): readLock/Unlock 实现共享的读取加/解锁,线程数不限,有读取线程工作时...include #include #include #include #include "raii.h" /* * atomic实现读写资源锁...,独占写,共享读,禁止复制构造函数和'='赋值操作符 * WRITE_FIRST为true时为写优先模式,如果有线程等待读取(m_writeWaitCount>0)则等待,优先让写线程先获取锁 *

    1.8K20

    【Linux】进程间通信——共享内存

    共享内存(Shared Memory) 什么是共享内存 共享内存(Shared Memory)是一种 进程间通信(IPC) 机制,允许多个进程共享同一块物理内存,从而提高数据交换效率。...共享内存的特点 高效:数据直接在内存中共享,避免了进程间数据拷贝的开销。 进程可见:多个进程可以同时访问同一块共享内存,实现高速数据传输。...需要同步机制:由于多个进程可以并发访问共享内存,通常需要使用 信号量(Semaphore) 或 互斥锁(Mutex) 来防止数据竞争。...3.共享内存的主要函数 函数 作用 shmget() 创建或获取一个共享内存段 shmat() 将共享内存附加到进程地址空间 shmdt() 解除共享内存与进程的关联 shmctl() 控制共享内存(删除...通过 shmget、shmat、shmctl 等函数,Linux 系统为我们提供了灵活的共享内存操作接口。

    9210

    速通 Linux 共享内存原理

    共享内存是一个非常有意思的话题,一方面共享内存避免了通讯过程中的内存复制问题,是 Linux IPC 通讯中效率最高的一种。...从使用方式上讲,Linux 提供了三种共享内存的方式,包括 Unix 味的 POSIX 和 SysV 接口,还提供了直接文件映射内存的 mmap。...本文尝试分别介绍 Linux 共享内存的基本原理,并做一个 “违背祖宗的决定”,如何在 Golang 中使用共享内存。...= nil { return err } return nil } SysV 的共享内存实现是基于 tmpfs,tmpfs 是一个常用的基于内存的 fs,当在 tmpfs 中读写时,fs 中的内容会保存在内存中...总结 从原理上讲 Linux 共享内存的主要方式只有两种,一是基于文件的 mmap,另一种就是 tmpfs,用一张图描述 Linux 几种实现共享内存的方式:

    4.1K20
    领券