多个读取器和多个写入器(我的意思是多个)同步

2024-01-08

我正在开发一项功能,需要一种读/写锁的变体,该变体可以允许并发多个写入者。

标准读/写锁允许多个读取器或单个写入器同时运行。我需要一个可以同时允许多个读者或多个作者的变体。因此,它永远不应该允许读者和作者同时存在。但是,可以同时允许多个作者或多个读者。

我希望我说清楚了。到目前为止我找不到任何现有的算法。我可以想出几种方法来使用一些队列等来做到这一点。但是,我不想冒险自己做这件事,除非不存在。

你们知道现有的方案吗?

Thanks,


您正在寻找的概念是可重入锁。如果锁已经被占用,您需要能够尝试获取锁并且不会被阻塞(这称为可重入锁)。 Java 中有可重入锁的本机实现,因此我将用 Java 来说明这个示例。 (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html).

因为当使用 tryLock() 时,如果锁不可用,您不会被阻止,您的写入器/读取器可以继续。但是,只有当您确定没有人在读/写时,您才想释放锁,因此您需要保留读者和作者的计数。您需要同步此计数器或使用允许原子递增/递减的本机atomicInteger。在这个例子中,我使用了原子整数。

Class ReadAndWrite {
 private ReentrantLock readLock;
 private ReentrantLock writeLock;
 private AtomicInteger readers;
 private AtomicInteger writers;
 private File file;

 public void write() {
   if (!writeLock.isLocked()) {
    readLock.tryLock();
    writers.incrementAndGet(); // Increment the number of current writers
    // ***** Write your stuff *****
    writers.decrementAndGet(); // Decrement the number of current writers
    if (readLock.isHeldByCurrentThread()) {
     while(writers != 0); // Wait until all writers are finished to release the lock
     readLock.unlock();
    }
   } else {
     writeLock.lock();
     write();
   }
  }

 public void read() {
   if (!readLock.isLocked()) {
    writeLock.tryLock();
    readers.incrementAndGet(); 
    // ***** read your stuff *****
    readers.decrementAndGet(); // Decrement the number of current read
    if (writeLock.isHeldByCurrentThread()) {
     while(readers != 0); // Wait until all writers are finished to release the lock
     writeLock.unlock();
    }
   } else {
     readLock.lock();
     read();
   }
  }

这里发生了什么事:首先,您检查您的锁是否已锁定,以了解您是否可以执行您要执行的操作。如果它被锁定,则意味着您无法读取或写入,因此您使用锁定将自己置于等待状态,并在再次释放锁定时重新调用相同的操作。

如果它没有被锁定,那么您可以使用 tryLock 锁定其他操作(如果您要读取,则锁定写入,反之亦然)。如果已经锁定,tryLock 不会阻塞,因此多个写入者可以同时写入,多个读取者可以同时读取。当与你做同样事情的线程数量达到 0 时,这意味着无论谁首先持有锁,现在都可以释放它。此解决方案的唯一不便之处在于,持有锁的线程必须保持活动状态,直到每个人都完成操作才能释放它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多个读取器和多个写入器(我的意思是多个)同步 的相关文章

  • 如何在unix中移动或复制“find”命令列出的文件?

    我有使用下面的命令看到的某些文件的列表 但是如何将列出的这些文件复制到另一个文件夹 例如 test 中 find mtime 1 exec du hc 添加到 Eric Jablow 的答案中 这是一个可能的解决方案 它对我有用 linux
  • 如何在 bash 上运行 MySQL 命令?

    以下代码在命令行上运行 mysql user myusername password mypassword database mydatabase execute DROP DATABASE myusername CREATE DATABA
  • 在 SQL Server 中获取帐户“锁定”状态

    我想解锁 SQL Server 中的一个帐户 在解锁之前 我必须检查该帐户是否被锁定 我只想在帐户被锁定时解锁 是否有任何 SQL 查询或存储过程来获取 SQL 用户的 锁定 状态 代表 Alex K 发布答案 SELECT LOGINPR
  • D 并发写入缓冲区

    假设您有一个大小为 N 的缓冲区 必须将其设置为确定的值 例如零或其他值 缓冲区中的此值设置分为 M 个线程 每个线程处理缓冲区的 N M 个元素 缓冲区不能immutable 因为我们改变了值 消息传递也不起作用 因为禁止传递 ref 或
  • Scala 中的超时未来

    假设我有一个函数 它调用一个阻塞可中断的手术 我想在超时的情况下异步运行它 也就是说 我想在超时到期时中断该功能 所以我正在尝试做这样的事情 import scala util Try import scala concurrent Fut
  • 如何在C中同时运行两个子进程?

    所以我开始学习并发编程 但由于某种原因我什至无法掌握基础知识 我有一个名为 fork c 的文件 其中包含一个 main 方法 在此方法中 我将 main 分叉两次 分别进入子进程 1 和 2 在孩子 1 中 我打印了字符 A 50 次 在
  • 如何从外语线程调用Python函数(C++)

    我正在开发一个程序 使用 DirectShow 来抓取音频数据 媒体文件 DirectShow 使用线程将音频数据传递给回调 我的程序中的函数 然后我让该回调函数调用另一个函数 Python 中的函数 我使用 Boost Python 来包
  • 有条件减少 CUDA

    我需要总结一下100000值存储在数组中 但带有条件 有没有办法在 CUDA 中做到这一点以快速产生结果 任何人都可以发布一个小代码来做到这一点吗 我认为 要执行条件约简 您可以直接将条件引入为乘法0 假 或1 真 加数 换句话说 假设您希
  • 如何在gnuplot中将字符串转换为数字

    有没有办法将表示数字 以科学格式 的字符串转换为 gnuplot 中的数字 IE stringnumber 1 0e0 number myconvert stringnumber plot 1 1 number 我可能使用 shell 命令
  • scala.concurrent.blocking - 它实际上做了什么?

    我花了一段时间学习 Scala 执行上下文 底层线程模型和并发性的主题 你能解释一下通过什么方式吗scala concurrent blocking 调整运行时行为 and 可以提高性能或避免死锁 如中所述scaladoc http www
  • XAMPP Windows 上的 Php Cron 作业

    嗯 我是这个词的新手CRON 据我所知 这是一个Unix安排特定操作在定义的时间间隔后执行的概念 我需要运行一个php文件 每小时更新一次数据库 但我的困惑在于安排执行 我在用XAMPP用于 Windows 7 上的本地开发测试 我发现了什
  • Android SyncAdapter 回调

    我已经按照 SDK 中的 SimpleSyncAdapter 示例项目的思路实现了 SyncAdapter AccountManager 和私有 ContentProvider 一切都运转良好 现在 当从远程服务器下载了设置了特定标志的新行
  • 如何读取 UDP 连接直至超时?

    我需要读取 UDP 流量 直到超时 我可以通过在 UDPConn 上调用 SetDeadline 并循环直到出现 I O 超时错误来做到这一点 但这看起来很黑客 基于错误条件的流量控制 下面的代码片段看起来更正确 但并没有终止 在生产中 这
  • 使用 grep 进行多种搜索模式

    考虑我有以下数据流 BODY1 attrib1 someval11 attrib2 someval12 attrib3 someval13 BODY2 attrib1 someval21 attrib2 someval22 attrib3
  • 父进程和子进程如何进行信号量操作?

    semget 调用是否在父进程和子进程之间共享信号量 我有这段代码 对于相同的代码 我观察到如果父进程首先运行 子进程有时会获得更改后的信号量值 但是当子进程首先运行时 父进程似乎永远不会携带更改后的信号量 为什么会发生这种情况 谁能向我解
  • 在 Unix 上,我应该对 errno 使用 system_category 还是 generic_category ?

    C 0x 有两个预定义的error category对象 generic category and system category 据我目前所知 system category 应用于操作系统返回的错误 并且generic category
  • 关闭 python 后让进程保持运行

    我希望在终止原始进程后继续运行进程 以下代码在终止原始进程后不会使其进程保持运行 args yes Popen args shell True stdout None stdin None stderror None 我已经尝试了我能想到的
  • 使用 sed 将反斜杠替换为斜杠[重复]

    这个问题在这里已经有答案了 我需要更换 with 我有一个文件 其中包含 test test2 test3 test4 I tried VRS Ruta cat ruta lst sed s g sed s g output test te
  • 命名互斥体的 Mono 替代方案

    在 Windows NET 上 命名的互斥体可用于同步多个进程 不幸的是 Mono 在 Linux 上不太支持这一点 他们的发行说明 http www mono project com Release Notes Mono 2 8 Shar
  • 有没有办法让我的程序用更少的代码运行?

    我为学校作业编写了以下代码 它编译并打印所有正确的消息 但出于我自己的好奇心 我想知道我的代码是否可以缩短并且仍然有效 我尝试了 signal 而不是 sigaction 但我听说 sigaction 比 signal 更受青睐 此外 此任

随机推荐

  • backgroundTaskHost.exe 退出并显示代码 1 (0x1)

    我正在创建一个 Windows 应用商店应用程序 该应用程序具有用于后台任务的 Windows 运行时组件 该解决方案在 Visual Studio 中构建时没有任何问题 但当触发后台任务时 它总是失败并显示消息 程序 4204 backg
  • 如何使用 Dapper.Contrib 正确“单一化”表名?

    我有一个 Net Core 3 1 控制台应用程序 在SQL Server数据库中 我有单数名称的表 与我的POCO类相同 这方便匹配和维护 对于我想使用的插入 更新和删除操作Dapper Contrib图书馆 但是 当我运行 Insert
  • Qsort 在 C++ 中不适用于哪些类型?

    std sort通过使用交换元素std swap 它又使用复制构造函数和赋值运算符 保证您在交换值时获得正确的语义 qsort通过简单地交换元素的底层位来交换元素 忽略与要交换的类型相关的任何语义 虽然qsort尽管不了解您正在排序的类型的
  • 将变换应用于 UITextView - 防止内容调整大小

    当我将旋转变换应用于UITextView然后点击里面开始编辑 看起来内容尺寸自动变宽了 内容视图的新宽度是旋转视图的边界框的宽度 例如 给定一个宽度为 500 高度为 400 的文本框 并旋转 30 度 新的内容宽度将为 500 cos 3
  • Cassandra 大量 SSTable

    启动一些长时间运行的写入作业 使用 Spark Cassandra 连接器从 Apache Spark 作业批量插入 后 Cassandra v 2 1 为目标表创建了数千个 SSTable 超过 4500 个 次要压缩阈值设置为默认值 4
  • Spark SQL - 如何将 DataFrame 写入文本文件?

    我在用Spark SQL用于读取镶木地板和写入镶木地板文件 但有些情况下 我需要写DataFrame作为文本文件而不是 Json 或 Parquet 是否有任何支持的默认方法或者我必须将该 DataFrame 转换为RDD然后使用saveA
  • Windows 版 Git:致命:早期 EOF

    昨天我安装了一个新的 Git windows 服务器 2 6 4 它与 Mac git 客户端 git 协议 运行良好 今天我正在努力让第二个客户端 Windows 7 正常工作 在尝试使其工作的过程中 我已将 Windows 服务器和客户
  • 本地主机上的 Azure Functions 代理 404

    我有一个 Azure Function App 其 URL 处有一个函数http localhost 7072 api create room以及其他功能 这个特殊的函数是一个HTTPTrigger允许匿名访问并接受GET verb Htt
  • 从 LINQpad 迁移到正确的 Visual Studio 项目?

    我正在 LINQpad 中学习 LINQ to SQL 这很棒 但是背后发生了很多我不太理解的魔法 我正在使用可选的 IQ 驱动程序连接到 Oracle 数据库 该驱动程序可以在 LINQpad 内部下载 我的查询正在运行 现在我需要将其移
  • 发布实现接口的 F# 类时的反射/C# 键入错误

    我有一个用 C 编写的接口 但在用 F 实现它时 我注意到一些奇怪的地方 F 类必须先转换为接口 然后 C 才能使用它 转换后 WPF 无法读取其属性 绑定失败且 SNOOP 无法反映它 我可以用 C 代码包装该对象 一切正常 界面 pub
  • Deflate压缩块的结构

    我在理解 Deflate 算法时遇到困难 RFC 1951 https www rfc editor org rfc rfc1951 TL DR如何解析Deflate压缩块4be4 0200 我创建了一个包含字母和换行符的文件a n在里面
  • 我应该在 Objective C 中哪里初始化变量?

    在 Objective C 中 我应该覆盖 init 方法来初始化我的变量吗 如果变量是属性 我仍然可以通过通常的方式访问它们来设置其初始值吗 在 Objective C 中 我应该覆盖 init 方法来初始化我的变量吗 是的 具体来说 指
  • Rails 3“最后”方法从 ActiveRecord 输出返回错误结果

    我的控制器中有以下代码 items Item where user id gt 1 order updated at DESC limit 2 oldest item items last 出于某种原因 我猜测这与我最近升级到 Rails
  • 缓存控制的默认值是多少?

    我的问题是 有时浏览器会过度缓存某些资源 即使我已经修改了它们 但F5之后一切都很好 我整个下午都在研究这个案例 现在我完全理解了 Last Modified 或 Cache Control 的意义 我知道如何解决我的问题issue 只是
  • 如何使用 sed 删除从第一行开始到遇到模式 '[ERROR] -17-12-2015' 之前的行?

    我需要在遇到模式 ERROR 17 12 2015 之前删除从第一行到该行的行 目前我正在尝试以下命令 但不幸的是它没有找到模式本身 sed 1 ERROR 17 12 2015 d errLog 这里有什么问题吗 其次 上面的脚本还将删除
  • 如何在python中添加换行符?

    我刚刚用 python 编写了一个程序 但输出中的语句彼此太接近 那么如何在 python 中的两个语句之间添加换行符呢 您可以打印新行字符 print n numlines
  • Kafka 的 session.timeout.ms 和 max.poll.interval.ms 之间的区别

    AFAIK max poll interval ms 是在 Kafka 0 10 1 中引入的 然而 目前还不清楚什么时候我们可以同时使用 session timeout ms 和 max poll interval ms 考虑这样的用例
  • 从日期集合中查找平均日期 (Ruby)

    我有一个猜测表 每个猜测中都只有一个日期 我想知道如何将两个或多个日期转化为平均值 div 类似这样 但显然 Ruby 不允许我划分这两个日期 日期有点难用 你应该使用时间 尝试将日期转换为时间 require time foo time
  • 应用程序运行时 Xcode 4.5 选项卡消失

    更新 看起来每当 Xcode 4 5 开始运行应用程序时 查看 gt 隐藏选项卡栏 命令都会自动执行 这确实看起来像一个错误 这个单词tabs在这个问题中指的是我们在顶部看到的那个Xcode集成开发环境 不是 Cocoa Touch 中的标
  • 多个读取器和多个写入器(我的意思是多个)同步

    我正在开发一项功能 需要一种读 写锁的变体 该变体可以允许并发多个写入者 标准读 写锁允许多个读取器或单个写入器同时运行 我需要一个可以同时允许多个读者或多个作者的变体 因此 它永远不应该允许读者和作者同时存在 但是 可以同时允许多个作者或