【问题标题】:Is Java 8 streams atomic?Java 8 流是原子的吗?
【发布时间】:2017-02-14 06:01:16
【问题描述】:

我看了几篇文章,但我还是一头雾水。

我知道并行流将以利用 CPU 的并行方式执行。而且我相信子作业将作为原子单元执行,对吗?

但是常规的 Java 8 流呢?

如果我执行让我们说下一行代码:

users.stream().map(user->user.getUsername()).collect(Collectors.toList()); 

该行是否也会以线程安全/原子方式执行?

【问题讨论】:

  • 不,子作业不是作为原子单元执行的,但不太清楚你的意思是什么。顺序流在单个线程中执行,因此它们不必是线程安全的。
  • 那么,如果我有一个多线程系统,并且我使用的是顺序流,我可能会因为竞态条件而导致数据不一致?
  • 您是否有竞争条件与您所做的 Streams 处理无关。正如我所说,目前还不清楚您的想法
  • 流执行读取操作。当有人同时写作并且您没有采取措施时,您会遇到问题。正如 Marko Topolnik 已经指出的那样,无论您是否使用流,情况总是如此。
  • 如果getUsername方法没有副作用,流操作不会引入任何副作用。但是,要考虑它是线程安全的,您必须确保在操作进行时 没有人 正在修改 any 线程中的源列表。你只能写一个线程安全的program,它是all操作的全部,而不是线程安全的操作。如果你的程序格式正确,流操作也可以。

标签: java multithreading concurrency java-8 java-stream


【解决方案1】:

流 API 为管道的每个步骤定义了许多合同,如果其中任何一个被违反,则可能会发生不可预测的行为或异常。

  • Spliterator。请注意后期绑定、IMMUTABLE 和 CONCURRENT 属性,这些属性可能因各种来源而异。
  • 收集源通常指定其拆分器的性质,例如ConcurrentHashMap 报告其观点的 CONCURRENT,而 HashMap 没有。这意味着 hashmap 无法处理外部线程的修改或流管道内的干扰副作用。
  • 管道中的每个操作都定义了用户提供的方法应具有的属性,关键概念是non-interference、状态性和副作用。比较filterpeek
  • Collector/Collectors 并没有清楚地说明他们的要求,但提供的函数通常应该是无干扰的、无副作用的和无状态的,就像中间操作一样,尤其是在使用并发收集器时。李>

一般来说,如果你做的一切都正确,那么并行和顺序流都可以安全使用,即使在不支持并发修改的集合上也是如此。

如果您正在做违反这些要求的事情,那么顺序流可能会更宽容一些,但它们仍然可能会失败。

【讨论】:

    【解决方案2】:

    不存在一般线程安全或原子性之类的东西。原子字段更新仅对于访问同一变量的线程而言是原子的,synchronized 代码块对于仅在同一实例上同步的线程而言是原子/线程安全的。

    流操作本身是纯粹的本地操作,这甚至适用于并行流操作,因为参与该操作的线程与任何其他线程无关。如果您使用具有(非本地)副作用的函数,这是非常不鼓励的,没有保证,这些副作用没有额外的线程安全性或原子性。唯一的例外是终端操作 forEachforEachOrdered,它们旨在产生副作用,并且有据可查的有关多线程行为的文档。

    所以操作users.stream().map(user->user.getUsername()).collect(Collectors.toList()),假设方法getUsername()遵循契约并且没有副作用,对任何其他线程根本不可见。如果你以线程安全的方式将返回的列表发布给其他线程,它会是安全的,如果你让它以不安全的方式逃逸,将无法保证。如果您从不将结果发布到其他线程,则问题变得无关紧要。

    【讨论】:

    • 如果users 是一个实例变量 - 在流处理期间被其他线程修改的列表?
    • @Ekaterina 我认为,很明显,如果 users 可能被其他线程修改,您有责任确保这些修改不会干扰 Stream 操作。规则与迭代 users 的任何其他操作相同。
    【解决方案3】:

    一般不会。如果使用的Spliterator 具有CONCURRENT 特性,则流是线程安全的。

    【讨论】:

      猜你喜欢
      • 2014-01-23
      • 1970-01-01
      • 2013-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 2010-12-11
      相关资源
      最近更新 更多