在顺序执行的线程中使用 ArrayBuffer?

Use ArrayBuffer in sequentially executed Threads?

我有两个 Future,第二个在第一个结束后开始。两者都写入同一个 ArrayBuffer 实例,但由于它们是串行执行的(不是同时执行的),我认为它们不是同时执行的。

但是,我知道在两个或多个线程之间共享的变量有 @volatile 注释(@volatile 禁用缓存)。

由于第一个线程完成后,在 ArrayBuffer 实例中,可能有一些 缓存 正在进行,这使得第二个线程无法看到 ArrayBuffer的真实状态:我不确定这样使用ArrayBuffer是否安全。

在我的情况下缓存是否确实是一个问题,如果是这样的话:是否有推荐的方法让 ArrayBuffer 在内部使用 @volatile

问题不在于缓存本身,而是 ArrayBuffer 是一个复合体,有几个子字段必须同步更新以确保正确操作。您将需要使用线程同步工具来确保这一点。

class ArrayBufferWrapper[T](ab: ArrayBuffer[T]) {
  def add(item: T) = {
    this.synchronized {
      ab.add(item)
    }
  }
}

通过包装 ArrayBuffer,组件在当前线程中正确实现,并确保线程安全 add 操作。

不,这不安全。

这正是他们发明函数式编程的原因。如果您无论如何都在使用 Scala,不妨利用它提供的范例。

避免使用可变结构,或者至少在必须使用它们的极少数情况下,不要让它们脱离局部作用域。那么你将永远不必处理这样的问题。它们将不再存在。

告诉我们更多关于您正在尝试做什么的信息,我相信有人会建议一两个设计,而不涉及两个线程改变相同的结构。

如果(当且仅当)你将它[数组]传播到未来应该没问题:

val futureA = Future {
  val buf = ArrayBuffer(…)
  update(buf)
  buf
}

val futureB = futureA map {
  buf => moreUpdates(buf); buf
}

futureB foreach println // print the result of the transformations

从内存安全的角度来看这是可以的,因为 futureA happens-before onComplete 的完成(实际上 Future 上的所有转换都是在 [=12= 之上实现的) ]) 调用回调。在这种情况下 map.