与来自多个线程的数组的非锁定交互(在 Java 中)

阿斯卡尔·伊布拉吉莫夫

我需要从两个线程访问一个字符串数组。它必须非常快且线程安全。我不喜欢使用锁,我可以采取什么方法来制作无锁线程安全的字符串数组?我需要一个 Java 食谱。

寒意

根据定义,竞争线程共享的内存中唯一可用的线程安全写入是由 CPU 中的原子指令提供的操作。这与 Java 无关(至少,几乎所有时间),但值得注意的是,在并发环境中没有锁的写入是可能的。

所以,这就是说,如果你想写入数组,你可能需要有锁。锁是解决一般问题的方法。

但是,您可以愉快地在多个线程之间共享一个数组而不会出现问题,只要它们只从数组中读取即可。因此,如果您的数组是不可变的(或与此相关的任何其他对象),它将是线程安全的,因为永远不会有争用的机会。

因此,假设您想从两个不同的线程写入数组,但您担心争用。也许每个线程都想记录大量数据。这个问题有几种不同的解决方案:我将尝试解释一些。这并非详尽无遗,因为并发性是一个难以解决的问题,尽管有一些通用方法,但答案通常取决于具体情况。

  1. 最简单的方法

只需在写入数组时在数组上使用锁并查看它的执行情况。也许您现在实际上不需要担心性能问题。

  1. 使用生产者/消费者方法

与其让两个线程写入同一个数组,不如让每个线程“产生”值(可能将它们放在不同的线程安全队列中)并让另一个线程负责“消耗”这些值(将它们从队列中移除并放入它们)在数组中)。

如果顺序很重要,这种方法可能很难实现。但是您使用的是并发性,因此无论如何排序都是相当不确定的。

  1. 批量写入

这里的想法是您将要从每个线程放入数组中的值存储在它自己的临时值批次中。当批处理达到足够大的大小时,线程将锁定数组并写入整个批处理。

  1. 写入数组的不同部分

如果您知道数据的大小,则可以通过简单地不允许线程写入相同的索引范围来避免争用。您可以将数组除以线程数。每个线程在创建时都会被赋予一个数组的起始索引。

此选项可能适合您的需求(无锁、线程安全)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Entity Framework 6中使用来自多个线程的单个上下文

来自分类Dev

来自多个领域的Java的hashCode

来自分类Dev

数组中的多个对象(java)

来自分类Dev

数组中的多个对象(java)

来自分类Dev

在多个线程上同步Java中的队列

来自分类Dev

在Java中同时运行多个线程

来自分类Dev

来自频率数组的霍夫曼编码(在 Java 中)

来自分类Dev

单个查询中来自多个表的多个COUNT SELECTS

来自分类Dev

MySQL将来自多个表(外键)的数据合并到一个数组中

来自分类Dev

Java中的线程结构

来自分类Dev

Java中的线程中断

来自分类Dev

Java中的进程与线程

来自分类Dev

我在Java中的线程

来自分类Dev

暂停Java中的线程

来自分类Dev

线程中的Java请求

来自分类Dev

我在Java中的线程

来自分类Dev

Java中的线程管理

来自分类Dev

暂停Java中的线程

来自分类Dev

Java中的多线程

来自分类Dev

Java中的后台线程

来自分类Dev

Java线程中的异常

来自分类Dev

java中的异常线程

来自分类Dev

如何在grafana中堆叠来自多个来源的数据

来自分类Dev

在C中处理来自多个库的错误代码

来自分类Dev

在单个DataGridView中显示来自多个DataTables的行

来自分类Dev

组中来自多个列的前1个值

来自分类Dev

在MySQL中合并来自多个表的多行

来自分类Dev

如何在grafana中堆叠来自多个来源的数据

来自分类Dev

在 ACCESS 中显示来自多个源的 DataGridView