同步不经常更新的哈希图的最佳方式

2024-05-07

我有一个在应用程序中使用的 HashMap。数据是在应用程序初始加载期间从数据库填充的,然后它始终只是读取并且从不更新。会有多个线程不断地读取数据。由于数据永远不会更新,因此我们目前不使用任何同步,仅使用 HashMap。我们现在定义的方式是:

private volatile Map<Integer, MyData> myMap = new HashMap<>();

现在我们希望通过从数据库重新填充来每天更新一次地图中的数据。我打算做的是将数据从数据库获取到本地地图myLocalMap每天半夜说。一旦我将数据从数据库加载到myLocalMap我只会交换myMap指出这一点。

所以我担心的是,在我做的那一刻myMap = myLocalMap,是否有其他线程正在读取数据的可能性myMap得到空的或意外的结果? 如果是的话,我将不得不同步myMap。对于同步,我有以下选项:

synchronized(myMap) {} OR // synchronize all map get and update operations
ConcurrentHashMap OR
Collections.synchronizedMap(myMap)

但我对使用同步犹豫不决,因为那样我也会同步所有读取。我认为每天同步一次地图刷新过程会影响全天不断发生的所有地图读取。这尤其糟糕,因为我的应用程序中有许多地图都是通过这种方式读取和更新的。有什么想法/意见吗?谢谢!


当我执行 myMap = myLocalMap 时,是否有可能 从 myMap 读取数据的其他线程得到一个空或 意想不到的结果?

不,那里没有。读取和写入是原子的 http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html对于引用变量,这意味着整个操作同时发生,并且在整个操作完成之前结果对其他线程不可见。因此,任何从“myMap”读取的线程都将获得旧的 myMap 或新的 myMap,但永远不会获得空或不一致的结果。此外,使用volatile“myMap”上的关键字意味着所有线程将始终了解新数据:如果 myMap 已更新,则启动的任何读取操作after启动的更新操作将使用该更新后的值。

Oracle Java 教程的支持文档:

  • 对于引用变量和大多数原始变量(除 long 和 double 之外的所有类型),读取和写入都是原子的。
  • 对易失性变量的任何写入都会与同一变量的后续读取建立发生之前的关系

Vogella http://www.vogella.com/tutorials/JavaConcurrency/article.html:

如果一个变量是用 volatile 关键字声明的,那么它就是 保证任何读取该字段的线程都会看到最多 最近写入的值。

同样来自关于 Vogella 的同一篇文章:

Java 语言规范保证读或写 变量是原子操作

另请参阅this https://www.ibm.com/developerworks/java/library/j-jtp06197/参考,特别是“清单 3. 使用易失性变量进行安全的一次性发布”,它描述了一种与您的情况非常相似的场景。

顺便说一下,我同意 Giovanni 关于 ConcurrentHashMap 的观点。但在您的情况下,您不需要使用 ConcurrentHashMap,因为所有更新都发生在单个事务中,并且您只需调整 Map 以指向新数据。

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

同步不经常更新的哈希图的最佳方式 的相关文章

随机推荐

  • 具有 TINYTEXT 列的 CREATE TABLE 语句中出现语法错误 1064?

    这是我到目前为止的 MySQL 代码 CREATE DATABASE bankbase USE bankbase CREATE TABLE clienttable ClientID SMALLINT 15 NOT NULL DEFAULT
  • 分支 ASP.NET Core 管道身份验证

    我的应用程序当前正在使用基本身份验证 但我想转换到 OAuth 因此在短时间内需要使用两种类型的身份验证 有没有办法像这样分支我的 ASP NET Core 管道 public void Configure IApplicationBuil
  • 编程语言解析器的来源?

    我正在清理我的一个旧项目 该项目计算有关大型软件项目的许多简单指标 指标之一是文件 类 方法的长度 目前 我的代码 猜测 类 方法边界的位置基于非常粗略的算法 遍历文件 维护 当前深度 并在遇到未加引号的括号时调整它 当您返回到类或方法开始
  • style.css 在 WordPress 中不起作用

    我的 WordPress 有问题 我已经创建了所有需要的文件 包括 style css index php 等 但页面没有样式 在标题中 除其他外 我把这个
  • 使用 proto.io 让开关在 IE8 中工作

    Proto io 为使用 CSS 的开 关切换按钮提供了一个非常好的解决方案 但是 它在 IE8 中不起作用 http proto io freebies onoff http proto io freebies onoff 有谁知道如何用
  • 需要使用 Node.js 压缩整个目录

    我需要使用 Node js 压缩整个目录 我目前正在使用node zip 每次该进程运行时都会生成一个无效的ZIP文件 正如您可以从这个 Github 问题 https github com Stuk jszip issues 41 是否有
  • 如何像java中的make一样程序化生成塞尔达传说

    我将如何用java制作程序生成的地图 游戏本身就像塞尔达传说是程序生成的 有帮助吗 不久前的 塞尔达传说 地图使用等距平铺视图 您需要做的第一件事是将等距图块集加载到您的程序中 我确信您可以找到塞尔达图块集 然后 您需要决定如何按程序生成地
  • Jsch:命令输出不可用

    我正在尝试使用 jsch 连接到远程交换机并运行一些命令并提取输出 我可以使用 连接到交换机 但是命令输出在输入流中不可用 也许我没有以正确的方式做这件事 这是代码 session jsch getSession user 10 0 0 0
  • 如何在postman中从JSONArray获取JSONobject

    我正在尝试使用测试脚本自动化邮递员中的注册场景 我有以下 JsonArray 作为响应 id 1 name user A cntkp martin company kreativ tel 12345678 email email prote
  • Django:djcelery 从 celery import current_app as celery in virtualenv 导入错误

    好吧 我已经尝试了我和谷歌能想到的一切 我正在尝试在 Macbook Pro OSX 10 8 4 上的 virtualenv 下运行 django celery 我在激活 virtualenv 时使用 pip 安装了 django cel
  • 如何在 Vue.js 中排除文件(例如配置文件)?

    https cli vuejs org config configurewebpack https cli vuejs org config configurewebpack https cli vuejs org config chain
  • Windows 8 SDK 中的 DirectX

    Summary 是否应该从针对 Windows 8 的应用程序中删除 directX 包含文件 Details 我是 Windows 开发新手 我正在尝试使用 Visual Studio 2012 如果可能 在 Windows 8 上编译
  • 如何在 F# 中捕获任何异常(System.Exception)而不发出警告?

    我试图捕获异常 但编译器给出警告 此类型测试或向下转型将始终保持 let testFail try printfn Ready for failing failwith Fails with System ArgumentException
  • 是否有一个 clojure 函数可以“连接”两个地图列表?

    我正在寻找一个类似于sql中的join的连接函数 例如 这是两个地图列表 def a user id 1 name user 1 user id 2 name user 2 def b user id 2 email e 2 user id
  • 如何读取/理解目标主机上的ansible日志(由syslog编写)

    当你在某个主机上执行 ansible 时 它 会写入该主机上的 syslog 如下所示 Dec 1 15 00 22 run tools python ansible
  • 如何在 Python 中的每个单元测试之前和之后运行特定代码

    以下是我在文件中的测试的结构 Class setup 测试01测试02测试03拆除 我需要在每次测试之前和之后运行特定的代码 以前 我可以从设置中调用该代码 但在测试之后 我不知道该怎么做 显然 从拆卸中调用代码对于最后一个测试是有效的 但
  • 屏幕关闭时接近传感器不起作用?

    Hy 我有一个与接近传感器相关的问题 当我将手指放在上面时 我想关闭屏幕 当我拿开手指时 我想打开屏幕 我成功地完成了关闭部分 但是当我将手指从传感器上移开时 它似乎没有执行 onSensorChanged 方法 这是它的代码 public
  • PL/SQL 触发器问题

    我正在尝试编写一个触发器来填充包含员工更新工资信息的表 我现在遇到一个无法解决的问题 这是要填充的表 drop table SalUpdates cascade constraints create table SalUpdates Sal
  • 如何替换每行中出现的所有字符串?

    我想在以下脚本中将所有出现的 用户名 替换为 但它仅替换第一次出现的情况 ls al sed s username 这就是 sed 默认情况下的工作方式吗 提前致谢 你需要g 全局 修饰符 sed s username g
  • 同步不经常更新的哈希图的最佳方式

    我有一个在应用程序中使用的 HashMap 数据是在应用程序初始加载期间从数据库填充的 然后它始终只是读取并且从不更新 会有多个线程不断地读取数据 由于数据永远不会更新 因此我们目前不使用任何同步 仅使用 HashMap 我们现在定义的方式