2017-09-14 2 views
1

Je suis un peu confus si je suis en train de muter en toute sécurité mes cartes/mappes mutables à l'intérieur de mon acteur. Est-ce que quelqu'un peut me dire si ce code est thread-sûr et correct?Suis-je en train de muter en toute sécurité dans mes acteurs akka ou n'est-ce pas thread safe?

class SomeActor extends Actor { 
    val userQ = mutable.Queue.empty[User] 
    val tranQ = mutable.Map.empty[Int, Transaction] 

    def receive = { 
    case Blank1 => 
     if(userQ.isEmpty) 
     userQ ++= getNewUsers() 
    case Blank2 => 
     val companyProfile = for { 
     company <- api.getCompany() // Future[Company] 
     location <- api.getLoc() // Future[Location] 
     } yield CompanyProfile(company, location) 

     companyProfile.map { cp => 
     tranQ += cp.id -> cp.transaction // tranQ mutatated here 
     } 
    } 
} 

Puisque je mute le tranQ avec des contrats à terme, est-ce sûr? Je crois comprendre que chaque message d'acteur est géré de manière sérielle, donc, même si je suis peut-être mal vu, je peux utiliser un état mutable comme celui-ci.

Je suis juste confus si l'utiliser à l'intérieur d'un appel futur comme tranQ est sûr ou pas.

Répondre

7

Non, votre code n'est pas sécurisé.

Lorsqu'un acteur traite un message à la fois, vous perdrez cette garantie dès que Future sera impliqué. À ce stade, le code à l'intérieur du Future est exécuté sur un thread (potentiellement) différent et le message suivant peut être traité par l'acteur.

Un modèle typique pour contourner ce problème est d'envoyer un message avec le résultat de l'Future en utilisant le modèle pipeTo, comme ceci:

import akka.pattern.pipe 

def receive: Receive { 
    case MyMsg => 
    myFutureOperation() 
    .map(res => MyMsg2(res)) 
    .pipeTo(self) 
    case MyMsg2(res) => 
    // do mutation now 
} 

Plus d'informations sur l'utilisation de Future s se trouvent dans la documentation AKKA : http://doc.akka.io/docs/akka/2.5/scala/futures.html