Using future callback inside akka actor

前端 未结 4 1607
我在风中等你
我在风中等你 2021-02-13 12:24

I\'ve found in Akka docs:

When using future callbacks, such as onComplete, onSuccess, and onFailure, inside actors you need to carefully avoid closing ove

相关标签:
4条回答
  • 2021-02-13 12:47

    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.

    0 讨论(0)
  • 2021-02-13 12:48

    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.

    0 讨论(0)
  • 2021-02-13 12:55

    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.

    0 讨论(0)
  • 2021-02-13 13:11

    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.

    0 讨论(0)
提交回复
热议问题