Upgrade to Pro — share decks privately, control downloads, hide ads and more …

scala_multi_thread.pdf

fuzyco
July 19, 2018

 scala_multi_thread.pdf

fuzyco

July 19, 2018
Tweet

More Decks by fuzyco

Other Decks in Programming

Transcript

  1. SCALAͰͷϚϧνεϨου
    ॲཧʹ͍ͭͯ
    1

    View Slide

  2. ࠓ೔ͷൃදΛฉ͍ͯΘ͔Δ͜ͱ
    ‣ Java͕ఏڙ͢ΔඇಉظϞδϡʔϧͷಛ௃ɾϢʔεέʔε
    ‣ ActorϞσϧ͕ͲͷΑ͏ʹεϨουηʔϑΛ࣮ݱ͍ͯ͠Δ͔
    2

    View Slide

  3. 3
    ϚϧνεϨουͷॏཁੑ
    ‣ ϜʔΞͷ๏ଇͷ่յ
    CPUΫϩοΫ਺ͷ಄ଧͪ
    ‣ ϚϧνίΞϓϩηοα࣌୅ͷ౸དྷ
    ฒߦ/ฒྻʹϓϩάϥϜΛ࣮ߦ͢Δඞཁ͕͋Δ
    ҰͭͷϓϩάϥϜͰෳ਺ͷεϨουΛ࣮ߦ͢Δ͜ͱ
    εϨου̍
    ॲཧ
    εϨου2
    ॲཧ
    εϨου3
    ॲཧ
    ෳ਺ͷॲཧ͕ɺॱෆಉ΋͘͠͸ಉ࣌ʹى͜Γ͏Δ

    View Slide

  4. 4
    ϚϧνεϨουͷ೉͠͞
    • ಡΈॻ͖ͷڝ߹ͷͨΊʹɺλΠϛϯάʹΑͬͯ݁Ռ͕ҟͳΔ৔߹͕͋Δ
    • σουϩοΫ
    ‣ εϨουؒͷಉظॲཧ/ഉଞ੍ޚ
    ‣ ࢥ͏Α͏ʹύϑΥʔϚϯε͕޲্͠ͳ͍͜ͱ΋
    • ্ख͘ഉଞ੍ޚͰ͖ͳ͔ͬͨΓɺ༨ܭͳಉظॲཧ͕૸ΔͱٯʹύϑΥʔϚϯε͕Լ͕Δ

    View Slide

  5. 5
    ϚϧνεϨουؔ࿈༻ޠ
    ‣ ഉଞ੍ޚ
    ‣ εϨουηʔϑ
    ‣ ΞτϛοΫʢෆՄ෼ૢ࡞ʣ
    ෳ਺ͷτϥϯβΫγϣϯ͔Βಉ͡Ϧιʔεʹରͯ͠ɺ
    ಉ࣌ʹߋ৽ॲཧ͕ߦΘΕΔࡍʹɺσʔλͷ੔߹ੑΛอͭͨΊʹߦ͏ॲཧ
    ϚϧνεϨουͰಈ࡞ͤͯ͞΋໰୊ͷͳ͍ϓϩάϥϜͷ͜ͱ(σουϩοΫɺσʔλڝ߹͕ى͖ͳ͍)
    ଞͷεϨουʹ͸ׂΓࠐΈΛͤͣ͞ɺݱࡏߦ͍ͬͯΔมߋૢ࡞͕࣮֬ʹऴΘͬͨޙʹ࣮ߦͰ͖Δ͜ͱ

    View Slide

  6. 6
    ࠓ೔ग़ͯ͘ΔϞδϡʔϧ
    1. Volatileम০ࢠ
    2. Synchronizedम০ࢠ
    3. concurrent.atomicύοέʔδ
    4. ActorϞσϧ

    View Slide

  7. 7
    ࠓ೔ग़ͯ͘ΔϞδϡʔϧ
    1. Volatileम০ࢠ
    2. Synchronizedम০ࢠ
    3. concurrent.atomicύοέʔδ
    4. ActorϞσϧ

    View Slide

  8. 8
    Volatileम০ࢠ
    1.ίϯύΠϥͷ࠷దԽʢஔ͖׵͑ʣΛ๷ࢭ͢Δ
    2.ίϯύΠϥͷ࠷దԽʢϦΦʔμʔʣΛ๷ࢭ͢Δ
    3.volatileम০ࢠΛ෇༩͞Εͨม਺͸ɺ௚઀ϝΠϯϝϞϦʹอଘ͞Εɺ
    CPUΩϟογϡ΁ͷίϐʔͳͲ͕ى͖ͳ͍
    @volatile var flag = false // ௚઀ϝΠϯϝϞϦʹอଘ͞ΕΔ
    [ৄ͍͠ࢿྉ] http://kannokanno.hatenablog.com/entry/20120528/1338229536

    View Slide

  9. 9
    ϚϧνεϨουͷ࢓૊Έ
    εϨου1 ϝΠϯϝϞϦ εϨου2
    ಡΈࠐΈ
    ಡΈࠐΈ
    ॻ͖ࠐΈ
    Ճࢉ
    • ࣮ߦޮ཰Λ͋͛ΔͨΊʹɺ֤εϨου͸࡞ۀ༻ϝϞϦΛ͍࣋ͬͯΔ
    • جຊ͸࡞ۀ༻ϝϞϦʹରͯ͠ಡΈॻ͖͕ߦΘΕɺ
    ద౰ͳλΠϛϯάͰϝΠϯϝϞϦ΁ಉظ͢Δ
    ίϐʔ
    ಉظ
    ಉظ
    ίϐʔ

    View Slide

  10. 10
    Volatileม਺͕ղܾ͢Δ͜ͱ
    ϝΠϯϝϞϦ΁ͷಉظ͕஗Ε͍ͯΔ৔߹ɺ
    ผεϨου͕ࢀর͍ͯ͠Δ஋͸ݹ͍Մೳੑ͕͋Δ
    Volatileम০ࢠʹΑͬͯ௚઀ϝΠϯϝϞϦʹ
    อଘ͢Δ͜ͱʹΑͬͯɺ๷͙
    • ࣮ߦޮ཰Λ͋͛ΔͨΊʹɺ֤εϨου͸࡞ۀ༻ϝϞϦΛ͍࣋ͬͯΔ
    • جຊ͸࡞ۀ༻ϝϞϦʹରͯ͠ಡΈॻ͖͕ߦΘΕɺ
    ద౰ͳλΠϛϯάͰϝΠϯϝϞϦ΁ಉظ͢Δ

    View Slide

  11. 11
    Volatileम০ࢠ͕ղܾ͢Δ͜ͱ
    εϨου1 ϝΠϯϝϞϦ εϨου2
    ಡΈࠐΈ
    ಡΈࠐΈ
    ॻ͖ࠐΈ
    ॻ͖ࠐΈ
    Ճࢉ
    Ճࢉ
    Volatileम০ࢠʹΑͬͯ௚઀ϝΠϯϝϞϦʹ
    อଘ͢Δ͜ͱʹΑͬͯɺ๷͙

    View Slide

  12. 12
    VolatileϢʔεέʔε
    ҎԼͷ৚݅Λຬͨ͢৔߹ʹ࢖͑Δ
    1.ͦͷม਺΁ͷॻ͖ࠐΈ͕ɺͦͷม਺ͷݱࡏͷ஋ʹґଘ͠ͳ͍
    2.ͦͷม਺͕ɺଞͷม਺ͱͷෆมࣜʹ࢖ΘΕ͍ͯͳ͍

    1 ౓͚ͩൃੜ͢ΔॏཁͳϥΠϑαΠΫϧɾΠϕϯτͷൃੜΛࣔ͢ɺεςʔλεϑϥά
    private[akka] abstract class Mailbox(val messageQueue: MessageQueue)
    extends ForkJoinTask[Unit] with SystemMessageQueue with Runnable {
    @volatile
    var actor: ActorCell = _

    }
    Actor಺෦Ͱ΋࢖ΘΕ͍ͯΔ

    View Slide

  13. 13
    Volatileम০ࢠͷ໰୊఺
    ++΍+=ͱ͍ͬͨԋࢉ(ಡΈऔΓɺมߋɺ௥ՃͷҰ࿈ͷԋࢉ)͸ΞτϛοΫͰ͸ͳ͍
    (εϨουΛϩοΫ͠ͳ͍ͨΊ)
    ΞτϛοΫͳԋࢉʹ͸java.concurrent.atomicΛ࢖͏
    ϝιου΍ΦϒδΣΫτ୯ҐͰ෇༩Ͱ͖ͳ͍
    synchronizedͳΒͰ͖Δ

    View Slide

  14. 14
    ࠓ೔ग़ͯ͘ΔϞδϡʔϧ
    1. Volatileम০ࢠ
    2. Synchronizedम০ࢠ
    3. concurrent.atomicύοέʔδ
    4. ActorϞσϧ

    View Slide

  15. 15
    Synchronizedम০ࢠ
    Volatileम০ࢠʹ͸ͳ͍ϩοΫػߏΛ༻͍ͯɺ
    ΦϒδΣΫτ΍ϝιουʹରͯ͠ϩοΫΛ഑ஔ͢Δ͜ͱʹΑͬͯɺ
    ಉ࣌ʹෳ਺ͷεϨου͕ॲཧΛߦΘͳ͍Α͏ʹഉଞ੍ޚΛߦ͏
    def process() = synchronized {
    // ϝιουʹର͢Δഉଞ੍ޚ
    }
    def process() = obj.synchronized {
    // ΦϒδΣΫτʹର͢Δഉଞ੍ޚ
    }
    ࢖͍͜ͳͤΕ͹ɺෳࡶͳॲཧ΋҆શʹߦ͑Δ

    View Slide

  16. 16
    ϩοΫػߏ
    ͋ΔεϨου͕ΦϒδΣΫτͷϩοΫΛऔಘ͢ΔͱɺͦͷϩοΫΛղ์͢Δ·Ͱ
    ଞͷεϨου͸ͦͷΦϒδΣΫτͷϩοΫΛऔಘ͢Δ͜ͱ͕Ͱ͖ͣɺ଴ͨͳ͚Ε͹ͳΒͳ͍
    ഉଞ੍ޚΛ࣮ݱ͢Δػߏ

    View Slide

  17. 17
    SynchronizedϢʔεέʔε
    ෳ਺ͷεϨου͕ಉ࣌ʹॻ͖ࠐΈʹߦ͘
    def add(account: Account, n: Int) = {
    account.money += n
    Thread.sleep(1000)
    println(s"thread: ${Thread.currentThread().getId()}, money: ${account.money}")
    }
    val jane = new Account("Jane", 100)
    val t1 = thread { add(jane, 10) } // εϨου1
    val t2 = thread { add(jane, 70) } // εϨου2
    t1.join(); t2.join()
    class Account(val name: String, var money: Int)
    —————————————————————————
    thread: 1, money: 180
    thread: 2, money: 180
    εϨου1͕moneyΛදࣔ͢Δલʹɺ
    εϨου2͕moneyΛߋ৽͍ͯ͠Δ

    View Slide

  18. 18
    accountΦϒδΣΫτʹରͯ͠ϩοΫΛ͔͚ͯɺ
    ̍εϨου୯ҐͰ͔ͦ͠ͷaccountΦϒδΣΫτʹ
    ΞΫηεͰ͖ͳ͍Α͏ʹ͍ͯ͠Δ
    def add(account: Account, n: Int) = account.synchronized {
    account.money += n
    Thread.sleep(1000)
    println(s"thread: ${Thread.currentThread().getId()}, money: ${account.money}")
    }
    val jane = new Account("Jane", 100)
    val t1 = thread { add(jane, 10) } // εϨου1
    val t2 = thread { add(jane, 70) } // εϨου2
    t1.join(); t2.join()
    class Account(val name: String, var money: Int)
    —————————————————————————-
    thread: 1, money: 110
    thread: 2, money: 180
    ֤εϨου͕ஞ࣍తʹॲཧΛߦ͍ͬͯΔ
    SynchronizedϢʔεέʔε

    View Slide

  19. 19
    Synchronizedͷ໰୊఺
    def send(a: Account, b: Account, n: Int) = a.synchronized {
    b.synchronized {
    a.money -= n
    b.money += n
    }
    }
    val a = new Account("Jack", 1000)
    val b = new Account("Jill", 2000)
    val t1 = thread { for(i val t2 = thread { for(i t1.join(); t2.join()
    σουϩοΫ
    ͓ޓ͍͕ϩοΫΛղ์͞ΕΔͷΛ଴ͬͯ͠·͏

    View Slide

  20. 20
    Synchronizedͷ໰୊఺
    ύϑΥʔϚϯεͷ௿Լ
    synchronizedΛଟ༻͠ա͗Δͱɺ
    ฒྻͰಈ࡞͢΂͖ϝιουʹ΋ϩοΫ͕͔͔ͬͯɺ
    γϯάϧεϨουॲཧʹͳͬͯ͠·͏͜ͱ͕͋Δɻ
    ৔߹ʹΑͬͯ͸ɺγϯάϧεϨουॲཧΑΓ΋஗͘ͳΔՄೳੑ΋͋Δ

    View Slide

  21. 21
    ϩοΫػߏͷ໰୊఺
    1. ϩοΫ͸Ճࢉɾ݁߹Ͱ͖ͳ͍
    2. ϩοΫΛ෇͚๨ΕΔ
    3. ϩοΫΛෆ༻ҙʹ࢖͍͗ͯ͢஗͘ͳΔ
    4. ؒҧͬͨϩοΫΛೖΕͯ૝ఆ֎ͷॲཧ͕ൃੜ͢Δ
    5. ϩοΫͷ഑ஔͷॱংΛؒҧ͑Δ
    6. Τϥʔͷൃݟ͕೉͍͠ɺΤϥʔ͔Βͷ෮ؼ͕ࠔ೉

    View Slide

  22. 22
    ϩοΫػߏ͸σουϩοΫ ͳͲͷةݥੑΛؚΜͰ͍Δ
    ϩοΫΛઃܭ͔Βഉআʹ͢Δ͜ͱʹΑͬͯɺ
    ϚϧνεϨουϓϩάϥϛϯάΛ؆қʹ͢Δઃܭࢥ૝͕
    ෯Λ͖͔͖͍ͤͯͯΔ

    View Slide

  23. 23
    ࠓ೔ग़ͯ͘ΔϞδϡʔϧ
    1. Volatileम০ࢠ
    2. Synchronizedम০ࢠ
    3. concurrent.atomicύοέʔδ
    4. ActorϞσϧ

    View Slide

  24. 24
    atomicύοέʔδ
    ୯Ұͷม਺ʹର͢ΔϩοΫϑϦʔͰεϨουηʔϑͳϓϩάϥϛϯά
    Λαϙʔτ͢ΔΫϥεΛؚΉύοέʔδ
    • AtomicBoolean: BooleanܕΛѻ͏
    • AtomicInteger: IntegerܕΛѻ͏
    • AtomicLong: LongܕΛѻ͏
    • AtomicReference: ΦϒδΣΫτܕΛѻ͏
    • …

    View Slide

  25. 25
    Atomicม਺
    Volatileम০ࢠͷ͍ͭͨม਺ʹର͢Δ
    ΠϯΫϦϝϯτॲཧ͸ΞτϛοΫʹͳΒͳ͍
    private val LOOP = 100000000 // 1ԯճϧʔϓ
    @volatile private var counter = 0L
    def count() = {
    for { i }
    val t1 = thread { count() } // εϨου1
    val t2 = thread { count() } // εϨου2
    t1.join(); t2.join()
    println(s"counter: ${counter}”)
    ————————————————————
    counter: 101280698
    private val LOOP = 100000000 // 1ԯճϧʔϓ
    private val counter = new AtomicLong(0L)
    def count() = {
    for { i }
    val t1 = thread { count() } // εϨου1
    val t2 = thread { count() } // εϨου2
    t1.join(); t2.join()
    println(s"counter: ${counter}")
    ————————————————————
    counter: 200000000
    Atomicม਺͸ɺΞτϛοΫʹ
    ΠϯΫϦϝϯτॲཧ͕Մೳ

    View Slide

  26. 26
    Atomicม਺
    private val uid = new AtomicLong(0L)
    @tailrec def getUniqueId(): Long = {
    val oldUid = uid.get
    val newUid = oldUid + 1
    // uid͕oldUidͱ౳͚͠Ε͹ɺಉظతʹuidʹnewUidΛઃఆ͢Δ
    if(uid.compareAndSet(oldUid, newUid)) newUid
    // ࣦഊͨ͠৔߹͸ɺϦτϥΠ͢Δ
    else getUniqueId()
    }
    Atomicม਺ͷϝιου͸ϩοΫϑϦʔͳͷͰɺσουϩοΫ͕ى͖ͳ͍
    ϩοΫΛͤͣʹɺଞͷεϨου͕ม਺Λมߋ͢Δͱɺ
    CAS(CompareAndSwap)͕ݕग़ʢ·ͨ͸ࣦഊʣ͠ɺͦΕͷૢ࡞Λ܁Γฦ͢͜ͱ͕Ͱ͖Δ

    View Slide

  27. 27
    Atomicม਺Ϣʔεέʔε
    • ҆શੑͱ଱ো֐ੑͰධՁ͕ߴ͍
    (CASϕʔεͷฒߦΞϧΰϦζϜ͸ϩοΫϑϦʔͱݺ͹ΕΔ)
    • ύϑΥʔϚϯεʹ͓͍ͯ͸ɺsynchronizedͱ΄ͱΜͲҧ͍͕ͳ͍ͱݴΘΕ͍ͯΔ
    • ෳ਺ͷม਺ͷߋ৽ʹ͸޲͍͍ͯͳ͍

    ୯ҰͷΧ΢ϯλʔॲཧ
    Future಺෦Ͱ΋࢖ΘΕͯΔ
    object Future {
    def find[T](@deprecatedName('futurestravonce) futures: TraversableOnce[Future[T]])
    (@deprecatedName('predicate) p: T => Boolean)
    (implicit executor: ExecutionContext): Future[Option[T]] = {
    ……
    val ref = new AtomicInteger(futuresBuffer.size)
    ……
    if (ref.decrementAndGet == 0) {
    ???
    }
    ……
    }
    }

    View Slide

  28. 28
    ࠓ೔ग़ͯ͘ΔϞδϡʔϧ
    1. Volatileम০ࢠ
    2. Synchronizedम০ࢠ
    3. concurrent.atomicύοέʔδ
    4. ActorϞσϧ

    View Slide

  29. 29
    ActorϞσϧ

    View Slide

  30. 30
    ActorϞσϧ
    ΞΫλʔͱ͸ɺܰྔεϨου
    AkkaͰ͸1GBͷϝϞϦʔͰɺΞΫλʔΛ270ສݸੜ੒͢Δ͜ͱ͕Ͱ͖Δ
    ΞΫλʔ͸ϝοηʔδΛड৴͢ΔϝʔϧϘοΫεΛ࣋ͭ
    εϨου1 εϨου2
    ϝʔϧϘοΫε
    ϝʔϧϘοΫε

    View Slide

  31. 31
    ActorϞσϧ͸εϨουηʔϑ
    “ϝοηʔδΛૹΔਓ͸ड͚औΔਓͷঢ়ଶʹؔΘΒͣͲΜͲΜϝοηʔδΛૹ৴Ͱ͖Δɻ
    ϝοηʔδΛड͚औΔਓ͸Ωϡʔʹཷ·ͬͨϝοηʔδͷ಺༰Λॱ࣍ॲཧ͢ΔͨΊɺ
    ΞΫλʔ͕ॴ༗͍ͯ͠ΔΠϯελϯεʹඇಉظʹΞΫηε͞ΕΔ͜ͱ͸ͳ͘εϨουηʔϑʹͳΔɻ”

    View Slide

  32. 32
    ActorϞσϧ͸εϨουηʔϑ
    ΞΫλʔ͸಺෦ʹϛϡʔλϒϧͳঢ়ଶΛ࣋ͭ͜ͱ͕Ͱ͖ɺ
    ͦΕΛ҆શʹߋ৽͢Δ͜ͱ͕Ͱ͖Δ
    class GreetActor(val who: String) extends Actor {
    var greeting = ""
    def receive = {
    case `who` => greeting = s"hello, $who"
    case msg => sender ! msg
    }
    }

    View Slide

  33. 33
    ΞΫλʔ͸಺෦ʹϛϡʔλϒϧͳঢ়ଶΛ࣋ͭ͜ͱ͕Ͱ͖ɺ
    ͦΕΛ҆શʹߋ৽͢Δ͜ͱ͕Ͱ͖Δ
    class GreetActor(val who: String) extends Actor {
    var greeting = ""
    def receive = {
    case `who` => greeting = s"hello, $who"
    case msg => sender ! msg
    }
    }
    ଞͷεϨου͔Βvarͷมߋ͸ผͷεϨου͔Βݟ͍͑ͯΔͱ͸ݶΒͳ͍ͷʹɺ
    ͳͥvarม਺ʹ@volatileએݴΛ͠ͳͯ͘΋େৎ෉ͳͷ͔ʁ
    ActorϞσϧ͸εϨουηʔϑ

    View Slide

  34. 34
    Akka͕อূ͍ͯ͠Δϧʔϧ
    [Ҿ༻] https://doc.akka.io/docs/akka/2.4.7/general/jmm.html#Actors_and_the_Java_Memory_Model
    1. The actor send rule
    2. The actor subsequent processing rule

    View Slide

  35. 35
    1. The actor send rule
    ΞΫλʔ΁ͷϝοηʔδૹ৴͸ɺ
    ͦͷΞΫλʔ͕ͦͷϝοηʔδΛड৴͢Δલʹى͖Δ
    “Ξϯό΢ϯσουϝʔϧϘοΫεͷ৔߹ConcurrentLinkedQueueΛ࢖͏͜ͱͰvolatile writeΛߦ͍ɺ
    ό΢ϯσουϝʔϧϘοΫεͷ৔߹͸LinkedBlockingQueueΛ࢖͏͜ͱͰϩοΫΛߦ͏”

    View Slide

  36. 36
    2. The actor subsequent processing rule
    ΞΫλʔͰͷ͋Δϝοηʔδͷॲཧ͸ɺ
    ͦͷΞΫλʔͰͷ࣍ͷϝοηʔδͷॲཧͷલʹى͜Δ
    “Ҏલͷϝοηʔδॲཧ࣌ʹߦͬͨॻ͖ࠐΈ͸ಉظ͞Εɺ
    ࣍ͷϝοηʔδΛॲཧ͢Δͱ͖ʹ؍ଌͰ͖Δ͜ͱ͕อূ͞ΕΔ”

    View Slide

  37. 37
    Akka͕อূ͍ͯ͠Δϧʔϧ
    [Ҿ༻] https://doc.akka.io/docs/akka/2.4.7/general/jmm.html#Actors_and_the_Java_Memory_Model
    1. The actor send rule
    ΞΫλʔ΁ͷϝοηʔδૹ৴͸ɺͦͷΞΫλʔ͕ͦͷϝοηʔδΛड৴͢Δલʹى͖Δ
    2. The actor subsequent processing rule
    ΞΫλʔͰͷ͋Δϝοηʔδͷॲཧ͸ɺͦͷΞΫλʔͰͷ࣍ͷϝοηʔδͷॲཧͷલʹى͜Δ
    ϝʔϧϘοΫεʹΑ࣮ͬͯݱ͍ͯ͠Δ

    View Slide

  38. 38
    ·ͱΊ
    • volatileએݴ͞Εͨม਺͸ɺৗʹϝϞϦ͔Β࠷৽ͷ஋Λऔಘ͢Δ͕ɺ
    ΞτϛοΫͳԋࢉ͸Ͱ͖ͳ͍
    • synchronized͸ϓϩάϥϚ্͕खʹ࢖Θͳ͍ͱɺ
    σουϩοΫ΍ύϑΥʔϚϯε௿ԼΛҾ͖ى͜͢
    • ϚϧνεϨου؀ڥͰͷ୯Ұม਺΁ͷΞτϛοΫͳԋࢉ͸
    concurrent.atomicύοέʔδʹؚ·ΕΔΦϒδΣΫτ͕ద͍ͯ͠Δ
    • ActorϞσϧ͸ϝʔϧϘοΫεʹΑͬͯεϨουηʔϑΛ࣮ݱ͍ͯ͠Δ

    View Slide