2017-09-14 76 views
1

如果我安全地改變我的演員內部的可變映射/隊列,我有點困惑。我是否安全地在我的akka​​演員中變異或者這不是線程安全的?

有人可以告訴我,如果這段代碼是線程安全和正確的?

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

既然我正在用期貨突變tranQ,這是否安全?

這是我的理解,每個演員的消息是以串行方式處理,所以雖然可能會皺眉,我可以使用像這樣的可變狀態。

我只是困惑,如果在將來調用像tranQ是安全的或不使用它。

回答

7

不,您的代碼不安全。

雖然演員一次處理一封郵件,但只要Future s已開具,您將失去此擔保。此時,Future中的代碼將在(可能)不同的線程上執行,並且下一條消息可能由actor來處理。

一個典型的模式來解決這個問題是使用pipeTo模式來發送郵件與Future的結果,就像這樣:

import akka.pattern.pipe 

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

更多有關使用Future S能阿卡的文檔中找到:http://doc.akka.io/docs/akka/2.5/scala/futures.html

相關問題