Akka手冊譯(一)——Akka和Java內(nèi)存模型

使用Lightbend平臺(tái)的主要好處,包括Scala和Akka,它簡化了編寫并發(fā)軟件的過程。本文討論如何Lightbend平臺(tái),尤其是Akka,并發(fā)應(yīng)用程序共享內(nèi)存的方法。

Java內(nèi)存模型

在Java 5之前,Java內(nèi)存模型(JMM)有誤的定義。由多個(gè)線程訪問共享內(nèi)存時(shí)可以得到各種奇怪的結(jié)果,如:

  • 線程看不到其它線程寫入的值:可見性問題;
  • 線程觀察其他線程的“不可能”行為,指令沒有按預(yù)期的順序執(zhí)行引起:指令重新排序的問題。
    Java 5的JSR 133解決了這些問題。JMM的一組規(guī)則是基于“發(fā)生前”的關(guān)系,這強(qiáng)制了當(dāng)一個(gè)內(nèi)存訪問發(fā)生在其它之前,相反地,允許在出現(xiàn)故障時(shí)發(fā)生。兩個(gè)例子說明這些規(guī)則:
  • 監(jiān)視鎖規(guī)則:釋放一個(gè)鎖之前每一個(gè)后繼得到相同的鎖。
  • 易失變量規(guī)則:寫易失性變量之前每一個(gè)后續(xù)的讀相同的易失性變量。
    盡管JMM看起來復(fù)雜,規(guī)范試圖找到一個(gè)易于使用和寫的能力之間的平衡性能,可伸縮的并發(fā)數(shù)據(jù)結(jié)構(gòu)。

Actor和Java內(nèi)存模型

Akka中Actor的實(shí)現(xiàn),有兩種方法在共享內(nèi)存環(huán)境下執(zhí)行多線程行為:

  • 如果一個(gè)消息發(fā)送到一個(gè)Actor(如由另一個(gè)Actor)。在大多數(shù)情況下,消息是不可變的,但是如果這個(gè)信息構(gòu)造不可變的對象是不正確的,沒有“發(fā)生前”的規(guī)則,接收者可能部分初始化數(shù)據(jù)結(jié)構(gòu),甚至可能值是憑空捏造的(長型/雙精度型)
  • 如果Actor在處理消息時(shí)改變內(nèi)部狀態(tài),并在片刻后訪問這個(gè)狀態(tài)在處理另一個(gè)消息時(shí)。深刻認(rèn)識(shí)到Actor模型中并不保證,同樣的線程會(huì)對不同消息執(zhí)行相同的Actor。
    為了避免Actor的可見性和重排序問題,Akka保證了下例兩個(gè)“發(fā)生前”的規(guī)則:
  • Actor發(fā)送規(guī)則:一個(gè)Actor發(fā)送消息發(fā)生之前由通一個(gè)Actor接收消息。
  • Actor后續(xù)處理規(guī)則:在處理消息發(fā)生前由同一個(gè)Actor處理后續(xù)消息。

注意
通俗的講改變Actor的內(nèi)部字段在下一個(gè)消息的可見。Actor中的字段不能是易失或相價(jià)的。

兩個(gè)規(guī)則僅適用于同一個(gè)Actor實(shí)例,對不同的Actor無效。

Futures和Java模型

完成Feature的“發(fā)生前”執(zhí)行調(diào)用的回調(diào)注冊。

我們建議不要封閉非final字段(在Java用final,在Scala中用val )如果你選擇封閉非final字段,它們必須被標(biāo)識(shí)為‘volatile’為了字段的當(dāng)前值是可見的回調(diào)。

如果封閉一個(gè)引用,需要確保實(shí)例是線程安全的。我們強(qiáng)烈建議遠(yuǎn)離使用鎖定的對象,因?yàn)樗谧顗牡那闆r下,引入性能問題和死鎖。這樣的同步是危險(xiǎn)的。

Actor和共享可變狀態(tài)

由于Akka運(yùn)行在JVM上仍有一些規(guī)則要遵循。

  • 封閉Actor內(nèi)部狀態(tài),并向其它線程暴露它。
1. class MyActor extends Actor {
2. var state = ...
3. def receive = {
4.    case _ =>
5.      //Wrongs
6. 
7.    // Very bad, shared mutable state,
8.    // will break your application in weird ways
9.      Future { state = NewState }
10.      anotherActor ? message onSuccess { r => state = r }
11. 
12.    // Very bad, "sender" changes for every message,
13.    // shared mutable state bug
14.      Future { expensiveCalculation(sender()) }
15. 
16.      //Rights
17. 
18.    // Completely safe, "self" is OK to close over
19.    // and it's an ActorRef, which is thread-safe
20.      Future { expensiveCalculation() } onComplete { f => self ! f.value.get }
21. 
22.    // Completely safe, we close over a fixed value
23.    // and it's an ActorRef, which is thread-safe
24.      val currentSender = sender()
25.      Future { expensiveCalculation(currentSender) }
26. }
27.}
  • 消息應(yīng)該是不可變的,這是為了避免共享可變狀態(tài)的陷阱。

上一篇
下一篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 并發(fā)系列的文章都是根據(jù)閱讀《Java 并發(fā)編程的藝術(shù)》這本書總結(jié)而來,想更深入學(xué)習(xí)的同學(xué)可以自行購買此書進(jìn)行學(xué)習(xí)。...
    小之丶閱讀 1,126評論 1 7
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,901評論 11 349
  • 有些時(shí)候心理明明愛著,我又不敢說出來,就算說出來了告訴自己也不會(huì)實(shí)現(xiàn),這可能是我比較悲觀的想法,試了又試可是又不想...
    lirs閱讀 714評論 1 1
  • 景邁山——夏無酷暑,冬無嚴(yán)寒,四季如春,雨量充沛,土壤肥沃,山花爛漫,果實(shí)累累,亞熱帶風(fēng)光旖旎。 山間云霧繚繞,山...
    芳華拾柒閱讀 268評論 7 3
  • ---相關(guān)和因果 在前面幾章里,心理學(xué)上證明個(gè)案的時(shí)候,往往用了很少有相關(guān)性的因素,得出因果關(guān)系,最后想證明某個(gè)結(jié)...
    折疊人生閱讀 414評論 0 1

友情鏈接更多精彩內(nèi)容