【问题标题】:Will the value of a variable updated by one thread eventually seen by another thread if not synchronized in Java?如果在 Java 中不同步,一个线程更新的变量的值最终会被另一个线程看到吗?
【发布时间】:2019-10-22 13:47:08
【问题描述】:

我知道如果一个变量的值由一个线程 A 更新,然后由另一个线程 B 读取,线程 B 可能看不到新值,并且 B 可能会得到一个陈旧的值。我的问题是,由于计算机速度非常快,我是否可以假设这个可能的延迟问题是毫秒级的,如果我们采用大约几分钟甚至几小时的时间尺度,B 最终会看到新值吗?

我问这个问题的原因是在我的代码中,我有一张地图保存了一些记录,并按以下方式工作:

  1. 用户向地图添加记录;

  2. 用户去做一些工作;

  3. 用户返回并删除记录;

许多用户同时执行此操作。第 1 步和第 3 步非常快并且在同一个线程中完成(具体来说是 AKKA 演员线程),第 2 步需要时间并且在不同的工作线程中完成。现在由于 step2 工作有时会失败,step 3 可能永远不会执行并且忘记的记录可能会累积在 map 中,我设置了一个调度程序线程来检查 map 是否有忘记的记录并将它们删除以避免内存泄漏,检查周期为几个小时失败很少发生,在这种情况下,使用非并发映射实际上可以吗?

【问题讨论】:

  • 您必须使用并发映射(或同步)。否则地图本身可能会进入不一致的状态。
  • 但是如果您使用 Akka Actor 来独占访问地图,Akka 将为您完成同步。 Actor 可以安全地修改其内部状态(这就是它们的用途)。所以你的调度器也应该让actor做清理工作。
  • 不,这样不行。 The Java Language Specification states 允许 Java 实现在没有同步/锁定的情况下从不检查来自当前线程以外的源的字段更新。

标签: java multithreading concurrency thread-safety


【解决方案1】:

如果单个 akka actor 线程负责映射访问并且映射是内存 local to that actor,那么应该不需要使用并发映射。这是因为没有并发访问,也没有任何竞争条件的机会。

问题是映射是否是更新/删除参与者和清理参与者/线程之间的共享内存。在这种情况下,必须进行同步,否则可能会出现数据竞争。

更新/删除参与者也支持某种清理消息(这将对您的参与者产生性能/吞吐量影响,但这是一种简单且安全的首选方法),这可以避免这种情况,它会阻塞以进行迭代地图和清理孤立记录。


要回答您的问题,如果地图在多个参与者/线程之间共享,则不行使用非并发(非同步)地图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    相关资源
    最近更新 更多