在顺序执行的线程中使用 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
.
我有两个 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
.