Scala期货和JMM

时间:2018-10-18 09:10:06

标签: scala concurrency jvm thread-safety future

我对JMM和Scala期货有疑问。

在以下代码中,我具有不可更改的 Data 类。我在一个线程(在Future apply主体内部)中创建它的一个实例,然后订阅完成事件。

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

object Hello extends App {
  Future {
    new Data(1, "2")
  }.foreach { d =>
    println(d)
  }
  Thread.sleep(100000)
}

class Data(var someInt: Int, var someString: String)

我们可以保证:

    是从同一线程(创建数据实例的地方)调用的
  1. foreach 正文?
  2. 如果没有,我们是否可以保证 foreach 正文中 Future.apply 先发生(根据JMM)中的操作?

4 个答案:

答案 0 :(得分:1)

完成happens-before回调执行。

免责声明:我是主要贡献者。

答案 1 :(得分:0)

我有一个类似的问题,我发现的是-

1)在文档Intellij中,对我来说很方便,它显示为

  

一旦值可用,将来会异步处理该值...

2)在https://docs.scala-lang.org/overviews/core/futures.html上说

  

结果将在将来完成后提供。

从根本上讲,我找不到明确指出存在内存障碍的地方。我怀疑,但这是一个安全的假设。否则,该语言将无法正常工作。

答案 2 :(得分:0)

您可以通过查看Promise / DefaultPromise / Future的源代码来很好地了解这一点,该源代码在执行上下文中安排foreach的回调/将其添加到侦听器,而无需任何特殊的逻辑来要求它在原始线程上运行...

但是您也可以通过尝试设置执行上下文和线程来进行实验性验证,以便在创建Future的{​​{1}}完成时已经将其他内容排队等待执行。< / p>

Data

我的输出:

  

在以下位置创建的数据:pool- $ n-thread-1

     

数据在以下位置完成:pool- $ n-thread-2

2。

在这里比我想要的要自信,但是我会给它一个机会:

是的

{p} implicit val context = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(2)) Future { new Data(1, "2") println("Data created on: " + Thread.currentThread().getName) Thread.sleep(100) }.foreach { _ => println("Data completed on: " + Thread.currentThread().getName) } Future { // occupies second thread Thread.sleep(1000) } Future { // queue for execution while first future is still executing Thread.sleep(2000) } DefaultPromise的基础构造,它包装了一个原子引用,其行为就像一个volatile变量。由于更新结果的写操作必须在将结果传递给侦听器的读取操作之前进行,因此它可以运行回调,因此JMM易失性变量规则将其转换为Future关系。

答案 3 :(得分:-1)

  1. 我认为不能保证从同一线程调用foreach
  2. 在将来成功完成之前,不会调用
  3. foreach。 onComplete是提供回调以处理Future结果的一种更惯用的方法。