Using future callback inside akka actor

試著忘記壹切 提交于 2021-02-06 15:27:25

问题


I've found in Akka docs:

When using future callbacks, such as onComplete, onSuccess, and onFailure, inside actors you need to carefully avoid closing over the containing actor’s reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback.

So does it mean that i should always use future pipeTo self and then call some functions? Or i can still use callbacks with method, then how should i avoid concurrency bugs?


回答1:


It means this:

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
      }
  }
}

In this example, both the actor's receive method, and the Future's onComplete change the mutable variable counter. In this toy example its easier to see, but the Future call might be nested methods that equally capture a mutable variable.

The issue is that the onComplete call might execute on a different thread to the actor itself, so its perfectly possible to have one thread executing receive and another executing onComplete thus giving you a race condition. Which negates the point of an actor in the first place.




回答2:


Yes, you should send a message to the enclosing actor if the callback mutates internal state of the actor. This is the easiest (and preferred) way to avoid races.




回答3:


I think I would be remiss if I did not mention here that I've made a small utility for circumventing this limitation. In other words, my answer to your question is No, you shouldn't use such an inconvenient workaround, you should use https://github.com/makoConstruct/RequestResponseActor

how does it work?

Basically, behind the futures and the promises, it transmits every query in a Request(id:Int, content:Any), and when it receives Response(id, result) it completes the future that corresponds to id with the value of result. It's also capable of transmitting failures, and as far as I can tell, akka can only register query timeouts. The RequestResponseActor supplies a special implicit execution context to apply to callbacks attached to the futures waiting for a Response message. This blunt execution context ensures they're executed while the Response message is being processed, thus ensuring the Actor has exclusive access to its state when the future's callbacks fire.




回答4:


Maybe this can help. It is an experiment I did and the test is quite conclusive... however, it is still an experiment, so do not take that as an expertise.

https://github.com/Adeynack/ScalaLearning/tree/master/ActorThreadingTest/src/main/scala/david/ActorThreadingTest

Open to comments or suggestions, of course.

Futures with actors is a subject I am very interested in.



来源:https://stackoverflow.com/questions/23908132/using-future-callback-inside-akka-actor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!