Actor&stm

2,053 views

Published on

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,053
On SlideShare
0
From Embeds
0
Number of Embeds
19
Actions
Shares
0
Downloads
8
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 巻き上げ。最適化していいことになっているから、\n
  • \n
  • スレッドAで書き込んだら、次のスレッドBで読み込めるとは限らない。\n
  • スレッドAで書き込んだら、次のスレッドBで読み込めるとは限らない。\n
  • スレッドAで書き込んだら、次のスレッドBで読み込めるとは限らない。\n
  • スレッドAで書き込んだら、次のスレッドBで読み込めるとは限らない。\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • (1)のVolatile Storeの結果が(2)のVolatile Loadで見えることが保証される。volatileでなくてもAtomicBooleanでもよいですね。可変な変数はいろいろややこしい。\n
  • 二つのスレッドが同時で動いたとしたら、x, yの結果はどうなりますか。\n
  • 同期化したメモリアクセスではないので、スレッドのスケジューリング次第で運任せ。\n
  • 結構な頻度でおこります。\n
  • 理屈はこうです。スレッドAの命令がリオーダーされた場合は0,0となります。\n
  • \n
  • \n
  • このように、そもそも人間のメンタルモデルから遠いノウハウを要求されてしまうのが、共有データ・ロックモデルです。ですから、本当にスレッドセーフで、スループットの出る マルチスレッドプログラミングができるプログラマは非常に少ないですし、これから目指すのも難しいということが言えます。\n
  • \n
  • 共有データロックモデルは簡単にデットロックを引き起こしてしまう可能性があるが、アクターは回避しやすい。これからは並行処理は、アクターから考えるべきです。\n
  • メッセージパッシングによる抽象度の高い並行処理モデルが、アクターモデルです。アクターとしてはErlangが有名。アクターはスレッドとメールボックスが一体になったようなオブジェクトです。アクターに何かを依頼するときはメッセージを送信します。アクターで受信したメッセージはキューで管理され、キューから取り出されたメッセージに応じた処理が実行されます。\n
  • リソースを共有しないので、シングルスレッドモデルでよいのです。\n
  • \n
  • \n
  • actorという関数を引数に取るファクトリメソッド。\n
  • receiveはブロックします。実行効率が悪い。もっと実行効率を上げるにはreactを使います。\n通常はアクターにはスレッドが割当てられます。 スレッドはたくさん作るとOutOfMemoryErrorを引き起こします。Javaで学んだようにスレッドをプーリングしてスレッドを再利用しなければなりません。reactはブロックせずに、スレッドを再利用します。ほとんどreceiveと同じことができますが、メッセージを処理しても制御を返しません。カレントスレッドは、次のアクターのために再利用されます。プログラム内のすべてのアクターがreactを使うなら1つのスレッド実行しようとします。ただし、コアの数によります。\n
  • リソースを共有しないので、メッセージだけで通信していれば、シングルスレッドモデルでよいのです。\n
  • しかし、落とし穴があってメッセージオブジェクトがmutableだとつらいことになります。とにかくImmutableにしないといろいろ面倒なことを考慮しないと、死にます。\n
  • \n
  • 同時複数のスレッドが同じ値を取得し、立て続けに加算した場合想定が崩れる。リードモディファイライトが、、\n
  • 同時複数のスレッドが同じ値を取得し、立て続けに加算した場合想定が崩れる。リードモディファイライトが、、\n
  • 結構な頻度でおこります。\n
  • 同時複数のスレッドが同じ値を取得し、立て続けに加算した場合想定が崩れる。リードモディファイライトが、、\n
  • \n
  • 同時複数のスレッドが同じ値を取得し、立て続けに加算した場合想定が崩れる。リードモディファイライトが、、\n
  • ロックを取得しないでアトミックな操作ができる。実行中のメモリIOを記録し、共有メモリに対しての変更を行う。\nロックがあればスレッド間の調停を行うが、この場合の整合性の検証は書き込み側ではなく、読み込み側に責任がある。トランザクション完了後に読み込み側で、他のスレッドで変更されていないかを検証させる。問題なければコミット、問題あればロールバックされてatomicの式は最初からやり直しになる。\n何がよいのかは、ロックコストを削減と、プログラムがわかりやすくなる。シングルスレッドで考慮すればいいか。デッドロック全く起きないか、トランザクションマネージャによって管理されているので安全です。\n\n
  • Actor&stm

    1. 1. Actor & STM じゅんいち☆かとう @j5ik2o
    2. 2. 並行処理 難しい
    3. 3. 何が難しいかスレッドセーフ が難しい
    4. 4. 原子性 可視性 順序性
    5. 5. スレッドと通信することってあるよねー
    6. 6. Q1.スレッドを止められるか...public class StopThread implements Runnable { private boolean terminate; public void run() { while (! terminate) { // なにかの処理 } } public void setTerminate(boolean terminate) { this. terminate = terminate; }}
    7. 7. HotSpot ServerVMなら... if (!terminate) { while(true){ // なにかの処理 } }
    8. 8. スレッド単位のセマンティクス
    9. 9. こう思ったら間違いのもとスレッドA terminate ← true terminateスレッドB true ← terminate
    10. 10. こう思ったら間違いのもとスレッドA terminate ← trueスレッドB false ← terminate true ← terminate
    11. 11. メモリモデルはスレッド単位スレッドA terminate ← true terminate(true)スレッドB false ← terminate terminate(false)
    12. 12. メモリモデルはスレッド単位スレッドA terminate ← true terminate(true) 大域のterminateスレッドB false ← terminate terminate(false)
    13. 13. メモリモデルはスレッド単位スレッドA terminate ← true terminate(true) 同期化しないと 見えない 大域のterminateスレッドB false ← terminate true ← terminate terminate(false) terminate(true)
    14. 14. これは可視性の問題 http://www.flickr.com/photos/teegardin/5547069087/sizes/m/in/photostream/
    15. 15. volatileェ...public class StopThread implements Runnable { private volatile boolean terminate; public void run() { // (2) Volatile Load while (! terminate) { // スレッドで行う処理 } } public void setTerminate(boolean terminate) { // (1) Volatile Store this. terminate = terminate; }}
    16. 16. Q2.x,yの結果はどうなる?x = 0; y = 0; a = 0; b = 0;class AThread extend class BThread extendRunnable { Runnable { @Override @Override public void run() { public void run() { a = 1; b = 1; x = b; y = a; } }} }
    17. 17. (1,1),(1,0),(0,1),(0,0)
    18. 18. 何回目で発生したか (x , y)004590 (1 , 1)005606 (0 , 0)045450 (0 , 1)045451 (1 , 0)105747 (0 , 0)129356 (0 , 0)
    19. 19. これは順序性の問題 http://www.flickr.com/photos/wahlander/3808866872/sizes/m/in/photostream/
    20. 20. (可変な)変数の共有と ロック争奪に基づく 共有データ・ ロックモデル
    21. 21. • 読み書きしようとしているデータが他 のスレッドから読み書きされないか。 どのようなロックがかけられている か。• メソッドを呼び出す際にどのような ロックを取得するか。その呼び出しに よってデットロックがないか。
    22. 22. Scala with Actor
    23. 23. 共有なしのメッセージ交換モデル
    24. 24. こんな感じ...
    25. 25. メッセージを受信するActorclass MyActor extends Actor { def act() = { // Runnable#run相当 loop { // while(true)の簡略表現 receive { // メッセージの待ち受け(ブロックする) case "end" => exit case msg: String => println(msg) } } }}val myactor = new MyActormyactor.start()// 文字列を渡すmyactor ! “Hello”// 終了メッセージを渡すmyactor ! “end”
    26. 26. 返事を返すActorval myactor = actor { loop { receive { case "end" => exit case "Hello" => reply("World") } }}// 戻り値を取得(返事が戻るまでブロック)val result = myactor !? “Hello”
    27. 27. Futureを返すActorval myactor = actor { loop { receive { case "end" => exit case numbers: List[Int] => 重いソート処理 reply(result) } }}// futureパターンval future = myactor !! largeNumberswhile(!future.isSet){ Thread.sleep(1000) }val result = future()
    28. 28. もっと簡潔にval myactor = actor { loop { receive { case "end" => exit case msg: String => println(msg) } }}// 文字列を渡す(ブロックしない)myactor ! “Hello”// 終了メッセージを渡す (ブロックしない)myactor ! “end”
    29. 29. reactはスレッドを節約するval myactor = actor { loop { react { case "end" => exit case numbers: List[Int] => 重いソート処理 reply(result) } // 制御を返さないので,ここは実行できない }}
    30. 30. リソースを共有しない利点class MyActor extends Actor { def act() = { // Runnable#run相当 loop { // while(true)の簡略表現 receive { // メッセージの待ち受け(ブロックする) case "end" => exit case msg: String => println(msg) } } }} シングルスレッド脳val myactor = new MyActormyactor.start() で考えればよい// 文字列を渡すmyactor ! “Hello”// 終了メッセージを渡すmyactor ! “end”
    31. 31. mutalbleなメッセージはやめようclass Money(var amount:BigDecimal, val actorA = new MyActor var currency: Currency) { def plus(add: Money):Unit = { val actorB = new MyActor var a = amount val money = new Money(10, a = a + add.amount amount = a Currency.getInstance("JPY" } )) // いろいろ省略 actorA ! ("set", money)} actorB ! ("set", money)class MyActor extends Actor { actorA ! ("add", money) var money: Money = _ actorB ! ("add", money) def act() = { loop { react { case "end" => exit case ("set", m) => money = m case ("add", m) => money.plus(m) } } }}
    32. 32. mutalbleなメッセージはやめようclass Money(var amount:BigDecimal, val actorA = new MyActor var currency: Currency) { def plus(add: Money):Unit = { val actorB = new MyActor var a = amount val money = new Money(10, a = a + add.amount amount = a Currency.getInstance("JPY" } )) // いろいろ省略 amount 参照の可視性 actorA ! ("set", money)} actorB ! ("set", money) plusメソッドの原子性class MyActor extends Actor { actorA ! ("add", money) var money: Money = _ actorB ! ("add", money) def act() = { loop { react { case "end" => exit case ("set", m) => money = m case ("add", m) => money.plus(m) } } }}
    33. 33. STM(Software Transcational Memoery)
    34. 34. スレッドセーフ? class Sequence { private var value = 0 def getValue = value // ↓ スレッドセーフか? def getAndIncrement() = { value += 1 // Java だと value++ value }}
    35. 35. スレッドセーフ?二つのスレッドからsequence.getAndIncrement()を1000回呼び出したら、最後に2000になるか
    36. 36. 0182 19980848 19983438 19983714 19983950 1998
    37. 37. レースコンディション
    38. 38. これは原子性の問題 http://www.flickr.com/photos/swellzombie/4303343824/sizes/m/in/photostream/
    39. 39. ロックで同期化class Sequence { private var value = 0 def getValue = value // ↓ ロックが必要 def getAndIncrement() = synchronized { value += 1 value }}
    40. 40. STM(Ref)class Sequence { private var value = Ref(0) def getValue = value.get def getAndIncrement() = atomic { value alter (_ + 1) }}class Ref[T] ...def alter(f: T T): T = { val value = f(get) set(value) value}

    ×