我在Akka docs中找到了:
当使用未来的回调,例如onComplete,onSuccess和onFailure时,你需要小心避免关闭包含actor的引用,即不要在回调中调用方法或访问封闭actor上的可变状态。 / p>
那么这是否意味着我应该总是使用future pipeTo self
然后调用一些函数?或者我仍然可以使用方法回调,那么我应该如何避免并发错误呢?
答案 0 :(得分:12)
这意味着:
class NotThreadSafeActor extends Actor {
import context.dispatcher
var counter = 0
def receive = {
case any =>
counter = counter + 1
Future {
// do something else on a future
Thread.sleep(2000)
}.onComplete {
_ => counter = counter + 1
}
}
}
在此示例中,actor的接收方法和Future的onComplete都会更改可变变量counter
。在这个玩具示例中,它更容易看到,但Future调用可能是嵌套方法,同样捕获可变变量。
问题是onComplete
调用可能在与actor本身不同的线程上执行,所以完全有可能让一个线程执行receive
而另一个执行onComplete
从而给你一场竞争。这首先否定了演员的观点。
答案 1 :(得分:4)
是的,如果回调改变了actor的内部状态,你应该向封闭的actor发送一条消息。这是避免比赛的最简单(也是首选)方法。
答案 2 :(得分:0)
我想如果我在这里没有提到我为避免这种限制而做了一个小实用工具,那将是我的疏忽。换句话说,我对你的问题的回答是否定的,你不应该使用这种不方便的解决方法,你应该使用https://github.com/makoConstruct/RequestResponseActor
它是如何运作的?
基本上,在期货和承诺背后,它会在
Request(id:Int, content:Any)
中传输每个查询,当它收到Response(id, result)
时,它会完成与id对应的未来,其值为result
。它也能够传输故障,据我所知,akka只能注册查询超时。 RequestResponseActor提供一个特殊的隐式执行上下文,以应用于附加到等待Response消息的期货的回调。这个钝的执行上下文确保在处理Response消息时它们被执行,从而确保Actor在未来的回调触发时具有对其状态的独占访问权。
答案 3 :(得分:0)
也许这会有所帮助。这是我做的一个实验,测试非常确定......但是,它仍然是一个实验,所以不要把它作为专业知识。
当然可以发表意见或建议。
演员的期货是我非常感兴趣的主题。