マルチスレッド プログラミングについて - 必要となる背景 - なぜ難しいのか - 難しさを解決するためにどのような手法があるのか のご紹介です。
主にマルチスレッド プログラミングの全体的な理解を得たいプログラマー向け。
ϚϧνεϨουϓϩάϥϛϯά- ͏ҙٛͱͦͷ͠͞ฤ -and- σʔλෆ߹Λղܾ͢Δฤ -saiya_moebius1
View Slide
ϚϧνεϨουϓϩάϥϛϯάલฤ- ͏ҙٛͱͦͷ͠͞ฤ -2
ϚϧνεϨου• Web Application Runtime• Ruby: puma (Heroku), Raptor (Passenger 5)• Java: tomcat, weblogic, GlassFish …• Native Application• Most of modern Apps (incl. Smartphone Apps)• Large scale batch process3
ϚϧνεϨου͕ۙͳ࣌• ੲ: ͦͦϋʔυతʹͦ͜·ͰΔҙٛͳ͠• গ͠ੲ: Ϛϧνϓϩηε(ޙड़)ͷ࣌• ࠷ۙ: ࣗͷॻ͍ͨΞϓϦ͕ϚϧνεϨουڥʹ͔ͬΔ / ࣗͰϚϧνεϨουରԠ͢Δ࣌ݱతϓϩάϥϛϯάͰۙʹͳ͖͍ͬͯͯΔϚϧνεϨου ϓϩάϥϛϯάʹ͍ͭͯ• ͦͦͲͷΑ͏ͳಈػͰɺԿͷͨΊʹΔͷ͔• ͲͷΑ͏ͳࠔ͕͋͞Δͷ͔• ͦΕʹର͢ΔΞϓϩʔνΛ͝հ4
εϨου• ϓϩάϥϜΛىಈ͢Δͱ࡞ΒΕΔͷ͕ϓϩηε• Windows Task Manager Ͱݟ͑Δ͋Ε• ϓϩηεϝϞϦྖҬΛ࣋ͭ• ϓϩάϥϜͷ࣮ߦঢ়ଶ͕εϨου• ࠓ͜ͷίʔυΛ࣮ߦͯ͠·͢Αɺͱ͍͏ঢ়ଶΛ࣋ͭhttp://www.atmarkit.co.jp/ait/articles/0503/12/news025.html• ϚϧνεϨου: ϓϩηεʹεϨουΛෳ࡞Δ• 1 ͭͷϝϞϦ(σʔλ)Λڞ༗͠ͳ͕ΒίʔυΛෳฒྻ࣮ߦ• Ϛϧνϓϩηε: ϓϩηεΛෳ࡞Δ (εϨου 1 ͭͮͭ)• ϝϞϦΛڞ༗͠ͳ͍ͰίʔυΛෳฒྻ࣮ߦ5
ͳͥϚϧνεϨου͔?• ϚϧνίΞ CPU ͷར༻• ୯ҰίΞੑೳͷਐาͷಷԽ (ϑϦʔϥϯνͷऴᖼ)• I/O ͪ࣌ؒͷ༗ޮ׆༻• Disk : Resource file, log file• Over Network : HTTP API call, DB query• ͨͤΔ͖Ͱͳ͍ॲཧΛͨͤͳ͍• ཪଆͰ࣌ؒͷֻ͔ΔॲཧΛ͠ɺදଆࢭΊͳ͍ίΞ : εϨουΛ࣮ߦ͢ΔͨΊͷϋʔυ, ݱత CPU ʹෳ͋Δ1 ͭͷ I/O ͪͷؒʹ CPU ສʙඦສճҎ্ͷ໋ྩΛॲཧͰ͖Δ6
ͳͥϚϧνϓϩηεͰͳ͍ʁϝϞϦ͕ڞ༗͞Εͳ͍͜ͱʹΑΔແବ͕͍ͬͺ͍:• ϓϩάϥϜࣗମΛෳϩʔυ• OS ଆͷ(CoW )͋Δ͕ɺಛʹ GC ͷ͋Δݴޠͱ૬ੑѱ• σʔλίϐʔͷΦʔόʔϔου• CPU ଆͷ࣋ͭΩϟογϡͷώοτͷԼ• ϛυϧΤΞɾΞϓϦଆͰͷϝϞԽ࣮ͱ૬• ΞϓϦଆ͕Βͳͯ͘ϛυϧΤΞଆͰ৭ʑ͍ͬͯΔ͜ͱ͕ଟ͍ϓϩάϥϜͦΕࣗମ͕ඦ MB ఔߦ͘͜ͱβϥϝϞԽ : ͍·ΘͤΔσʔλɾܭࢉ݁ՌΛอଘ͍͠ճ͢࠷దԽख๏7
࣮ʹదͳᄻ͑Ϛϧνϓϩηε֤͕ࣗࣗͷ͓ՈͰݸผʹ࡞ۀ͢Δ( ࡞ۀॴ͕ਓඞཁɺ࡞ۀաఔ݁ՌΛ૬ޓڞ༗͠ͳ͍ )ϚϧνεϨουશһ͕ҰՕॴͰڞಉ࡞ۀ͢Δ( ࡞ۀॴɺ࡞ۀͷதؒɾ࠷ऴ݁ՌશһͰڞ༗ )8ݫີʹɾ࣮ࡍͷ্࣮৭ʑͳࣄ͕͋Δ͕ɺ͜ͷࢿྉͰʮฒߦॲཧʹͯϝϞϦۭؒΛڞ༗͍ͯ͠Δ൱͔ʯͰ͍͚
ϚϧνεϨουʹͯ͠Έͨʂ → രࢮϚϧνεϨουݪཧతʹߴੑೳʂͨͩ͠ɺͦΕͪΌΜͱಈ͚ͷ…• ԿͰͳ͍ͣͷίʔυͰҟৗऴྃ͢Δ͜ͱ͕͋Δ• ܭࢉ݁Ռ͕߹ͬͯͳ͍͜ͱ͕͋Δ• ී௨ʹϛυϧͷػೳΛͬͨΒམͪΔ͜ͱ͕͋Δͱ͍֤ͬͨछόάΛ৯Β͏͜ͱ͕େมଟ͍9࡞ۀॴաఔڞ༗͍ͯ͠ΔͷͰɺޓ͍ͷॲཧ͕ѱ͍ҙຯͰ૬ޓ࡞༻ͯ͠͠·͏
Α͘ݴΘΕΔྫۜߦޱ࠲ͷᄻ͑ (200+200\ ༬͚ͨͷʹยํϩετ)http://www.atmarkit.co.jp/ait/articles/0505/25/news113.html
γϯάϧεϨουͷෳࡶϓϩάϥϜͷ࣮ߦεςοϓͱൺྫ:ͳΜ͔ॲཧ 1ϝϞϦεϨουͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 3ͳΜ͔ॲཧ 411
ϚϧνεϨουͷෳࡶશεϨου͕ಉ͡λΠϛϯάͰಈ͘ͳΒͱ͔͘…ͳΜ͔ॲཧ 1ϝϞϦෳεϨου͔ΒಡΈॻ͖εϨουͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 3ͳΜ͔ॲཧ 4ͳΜ͔ॲཧ 1εϨουͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 3ͳΜ͔ॲཧ 412
ϚϧνεϨουͷෳࡶ࣮ࡍಈ͚Δ࣌ʹಈ͘ͷͰɺॲཧεςοϓͷεϨουͷΈ߹Θ͕ͤ…ϝϞϦಡΈॻ͖͕ೖΓཚΕͯෆ߹εϨουͳΜ͔ॲཧ 1εϨουͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 1εϨουͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 1ͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 41000 Λ 4 ͢Δ͚ͩͰ 1 ஹ࣮ࡍͷϓϩμΫτͷෳࡶߋʹେͳΜ͔ॲཧ 3ͳΜ͔ॲཧ 313
͞Βʹ࠷దԽ͕ೖΔ͜ͱͰ…ݴޠॲཧܥɾCPU ͷ࠷దԽʮผεϨου͔Βಉ͕͡σʔλΛಡΈॻ͖͞Εͳ͍ʯલఏίϯύΠϥɾJIT ͷ࠷దԽྫ• ॲཧͷॱংೖΕସ͑ → ผͷεϨου͔ΒݟΔͱมͳॱংͰσʔλ͕ॻ͖ΘΔ• ϝϞϦͷಡΈॻ͖Λ 1 ճʹ·ͱΊΔ → มΛԿճಡΜͰݹ͍͕औΕͯ͠·͏CPU ͷ࠷దԽྫ• ໋ྩͷॱংೖΕସ͑, ϝϞϦͷಡΈॻ͖Λ·ͱΊΔ, ϝϞϦͷಡΈॻ͖தʹଞͷ໋ྩΛ࣮ߦ• ϝϞϦͷ༰ΛखݩʹΩϟογϡ (CPU Core ผͷΩϟογϡͦ͏Ͱͳ͍ͷ͋Δ)14
Ͳ͏͢Δ͔εϨουͳΜ͔ॲཧ 1εϨουͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 1εϨουͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 1ͳΜ͔ॲཧ 2ͳΜ͔ॲཧ 4ͳΜ͔ॲཧ 3ͳΜ͔ॲཧ 3ϝϞϦಡΈॻ͖͕ೖΓཚΕͯෆ߹ύϑΥʔϚϯεΛ֬อͭͭ͠σʔλෆ߹Λ͙͠ʂ→ ϚϧνεϨου ϓϩάϥϛϯάͷͨΊʹੵΈॏͶΒΕ͖ͯͨݟΛ׆༻15
ϚϧνεϨουϓϩάϥϛϯάޙฤ- σʔλෆ߹Λղܾ͢Δฤ -16
ෆ߹ʹରॲ͢ΔͨΊͷΞϓϩʔνಉ࣌ʹσʔλʹ৮ΕΔεϨουΛݶఆ͢Δܥ (ฒྻ, ൺֱతສೳ)• Lock / Semaphore• Read-Write Lock• Optimistic Lock (CAS loop)• Asynchronous Callback / Event Driven• Queueing / Pipelining• Messaging• Immutable Object (Atomic Reference, Hazard Pointer)• Local Variable, Thread Local Storageͦͦڝ߹͠ͳ͍͔ΒେৎͩΑܥ (ߴฒྻ, ϝϦοτେ)17
Lock (a.k.a Semaphore)1. σʔλͷಡΈɾॻ͖։࢝લʹϩοΫΛ֬อ2. σʔλͷಡΈɾॻ͖ྃޙʹϩοΫΛղ์ଞεϨου͕ϩοΫΛ֬อ͠Α͏ͱ͢Δͱɺ2 ·Ͱͨ͞ΕΔ• ෆ߹ͳσʔλॻ͖͑Λ͞Εͯ͠·͏৺͕ͳ͘ͳΔ• ͦͦಉ࣌ʹσʔλΛಡΈॻ͖͍ͯ͠ͳ͍18ॳֶऀ͚ʹհ͞Ε͕͕ͪͩɺ᠘͕ଟ͠ (ޙड़)͜ͷؒɺଞεϨουϩοΫΛ֬อͰ͖ͳ͍
Lock ͷ᠘ 0: ղ์࿙Ε• ͢ͰʹϩοΫ͕ѲΒΕ͍ͯΔͱɺ୭ϩοΫͰ͖ͳ͍• ϩοΫͷղ์͠Ε͕ҰՕॴͰ͋ΔͱγεςϜશମͷఀࢭʹ, ྫ͑͜ͷΑ͏ͳ:1. ୯ʹղ์ॲཧΛॻ͖Εͨ2. ޙ͔Β݅ذॲཧΛͨ͠෦Ͱղ์Ε3. ྫ֎ൃੜ࣌(ҟৗൃੜ࣌)ʹղ์͢ΔͨΊͷϑΥϩʔॲཧ͕ͳ͔ͬͨ4. ϑΥϩʔॲཧॻ͍͕ͯ͋ͬͨɺͦͷϑΥϩʔॲཧ్͕தͰҟৗऴྃ͢Δ͜ͱ͕͋ͬͨ5. εϨουڧ੍ऴྃ࣌ʹղ์͞Εͳ͍༷ͩͬͨ• synchronised (Java), lock (C#), RAII (C++) ͱ͍ͬͨݴޠػೳ͕͑Δہ໘Ͱੋ͕ඇͰ͏͠• ͨͩ͠OSɾݴޠॲཧܥɾϥΠϒϥϦͷݶքΛ͖ͪΜͱௐͯˍݕূͯ͠͏͜ͱ (ಛʹ্ه 3, 4, 5)• ݴޠػೳ͕͑ͳ͍ہ໘Ͱɺ্هͷΑ͏ͳ͋ΒΏΔέʔεΛఆͯ͠ॻ͘͠19
Lock ͷ᠘ 1: ੑೳ͕ग़ͳ͍• ฒߦͰॲཧΛ͢Δͷ͕ϚϧνεϨου• ͕ͩɺLock ΛѲΒΕ͍ͯΔͱɺ1 ͭҎ֎ͷεϨουͨ͞ΕΔฒߦॲཧͷͨΊʹฒߦॲཧ͠ͳ͍ࠜຊతໃ६…ϚϧνεϨουʹ͢Δ͜ͱͰಘ͔ͨͬͨੑೳ্͕ಘΒΕͳ͍20ଞͷεϨουΛ͋·Γͨͤͳ͍ͱ͍͏֬৴͕͋ΔͳΒΞϦ
Lock ͷ᠘ 2: Dead LockεϨουͦΕͧΕ͕ Lock Λอ࣋࣍ͷϩοΫΛཁٻ -> ͓ޓ͍Λػ -> ͣͬͱػ…Possible Solution:• ϩοΫ֫ಘͷॱংΛܾΊɺؾΛ͚࣮ͭͯ͢Δ• ࣮͕େมɺ(ઌड़ͷෳࡶੑͷͨΊ)όάΓ͍͢͠ςετࠔɺͱےѱ• Ұఆ࣌ؒҎ্ϩοΫऔΕͳ͔ͬͨΒ and/or Dead Lock ݕͨ͠Β rollback• rollback & retry Ͱ͖ΔΑ͏ͳॲཧ༰ͳΒ͋Γ (࣮ͷख͕ؒ૿͑Δ͕)21DBMS ͷߦϩοΫͰಉ͕͡ى͜Γ͑Δ͜ͱͰ༗໊MySQL (InnoDB) ͍खʹ rollback ʹରԠ͢Δ͜ͱΛڧ੍͍ͯ͠Δ
Lock ͷ᠘ 3: Unfairը໘ API ͳͲϦΞϧλΠϜͰΘΕΔ༻్Ͱɺॲཧͷਐḿ͕ภΒͳ͍ੑ࣭(fairness)͕ඞཁFairness ͕֬อ͞Ε͍ͯͳ͍߹ɺӡ࣍ୈͰಛఆͷεϨου͔Γͨ͞ΕΔ͜ͱ͕͋Δ• ଟ͘ͷ Lock ࣮ fairness อূ͕ͳ͍ͷͰɺʮҰ෦ͷϦΫΤετʹର͚ͯͩ͠Ϩεϙϯε͕ڧʹѱԽ͢Δʯͱ͍ͬͨঢ়͕ى͜ΔݪҼʹͳΔ• ݴޠॲཧܥɾϥΠϒϥϦʹΑͬͯΦϓγϣϯͰ fairness ΛอূͰ͖Δ Lock ࣮͋Δ• ͨͩ͠ɺଟ͘ʮઌணॱͰϩοΫ͢Δ͜ͱΛอূ͢Δʯͱ͍͏ҙຯͰͷ fairness อূ• fairness ͷҙຯ͕χʔζͱҰக͍ͯ͠Δ͔ཁҙ• ຊʹඞཁͩͬͨͷϩοΫઐ༗࣌ؒͰͷ fairness Ͱ͋ͬͨɺͱ͍ͬͨ͜ͱ͕ଟ͠• ͦ͏͍ͬͨ߹ɺޙड़ͷ pipeline ύλʔϯ(+ ༏ઌ͖Ωϡʔ)Λݕ౼͢͠22fair ͳϩοΫ࣮෦తʹ༏ઌ͖Ωϡʔʹͳ͍ͬͯΔͷ͕ଟ͍
Lock ͷ᠘ 4: ༏ઌॱҐͷٯసࢀߟ: ՐͰ͍͍ͬͨԿ͕ى͖ͨͷ͔? - Glenn Reeves http://www.unixuser.org/~euske/doc/risks-ja/mars.htmlPossible Solution:• Mars Pathfinder ͷ vxWorks ͷΑ͏ʹ͜ͷʹରॲ͢ΔͨΊͷ Semaphore ֦ு͕͋Εར༻͢Δ• lock ΛѲ͍ͬͯΔ࠷தͷॲཧΛ࣌ؒͰऴΘΒͤΔ (ଟ͘ͷܭࢉػϕετΤϑΥʔτࢤ…)• ͦͦ༏ઌλεΫϩοΫΛѲΒͳ͍Α͏ʹઃܭ͢Δ23
Read-Write LockLock ͷѥछ, σʔλΛಡΉ͚ͩͷॲཧ͕ෳฒྻͬͯσʔλෆ߹ͳ͍͜ͱΛ׆༻:• Read Lock : σʔλͷಡΈऔΓεϨουෳಉ࣮࣌ߦ OK• Write Lock : σʔλͷॻ͖ࠐΈεϨου͕͍ΔؒଞશһػLock ͷ᠘ 1, 3 (ੑೳ͕ग़ͳ͍, Unfair)͕؇͞ΕΔଟ͘ͷΞϓϦɾγεςϜͰߋ৽ܥΑΓࢀরܥΞΫηε͕1ܻҎ্ଟ͍ͨΊ༗༻Lock ͷ᠘ 2, 4 (Dead Lock, ༏ઌॱҐͷٯస)վળ͠ͳ͍Ճ͑ͯɺRead Lock தʹ Write Lock ͕ͪೖͬͨ߹ͷڍಈʹผͷ᠘͕͋ΔͷͰҙ( Write Lock ͕ͪ͋Δ߹ɺଟ͘ͷ࣮Ͱޙଓͷ Read Lock ཁٻͨͤΔ(Write Lock ͷͨΊʹ Reader ͕͍ͳ͍ঢ়ଶΛ࡞Ζ͏ͱ͢Δ)ɻͦͷ݁ՌɺWrite Lock Λ͍ͨͤͯΔ Read Lock ͕ผͷ Read Lock ΛؒతʹͨͤΔ͜ͱʹͳΓɺར༻ऀ͕ظ͍ͯ͠ΔͰ͋Ζ͏ฒྻੑ͕ຬͨ͞Εͳ͍ɻWrite Lock ͢Δଆ timeout ͖ͰϩοΫΛճࢼΈ͔ͯΒ timeout ͳ͠ͰϩοΫཁٻ͢ΔΑ͏ʹ͢ΔͳͲͷ workaround ͕ඞཁɻ)24ଟ͘ͷ RDBMS ͷ࣮ޙड़ͷ Versioning + ͜Ε
Optimistic Lock (CAS loop)Lock ͷѥछ, ͱΓ͋͑ͣखݩͰॲཧΛਐΊͯ͠·ͬͯɺ࠷ޙʹ߹ੑΛ୲อ:1. ॲཧ։࢝࣌ͰͷରσʔλΛऔಘ2. ॲཧΛਐΊΔɺͨͩ͠ॻ͖ࠐΉ༧ఆͷσʔλखݩʹஷΊ͓ͯ͘3. ͦͷޙϩοΫΛऔͬͯɺόʔδϣϯ൪߸Λ্͛ͭͭσʔλΛॻ͖ࠐΉ• ͨͩ͠ɺ1 Ҏ߱ʹผεϨου͔Βߋ৽͞Ε͍ͯͨͳΒɺ1 ͔ΒΓ͠• ࣗͷܭࢉ݁Ռ͕ӡྑ͘࠷৽Ͱ͋ͬͨͳΒॻ͖ࠐΉ• ͜ͷॲཧΛ 1 ໋ྩͰߴɾ҆શʹߦ͑Δ CAS (Compare and Swap) ໋ྩ͕Α͘ΘΕΔ֤छ Lock ͷ᠘ͦͷͷͷࠜຊରॲʹͳΒͳ͍͕ɺϩοΫظؒΛڱΊΔ͜ͱ͕Ͱ͖ΔͦΕʹΑ֤ͬͯछ Lock ͷ᠘(ੑೳ, fairness, ༏ઌॱҐٯస)͕؇͞ΕΔͨͩ͠ɺϦτϥΠ͕܁Γฦ͠ൃੜ͠ॲཧ͕Ҿ͘͜ͱ͋ΔͨΊɺඇৗʹunfair ͳڍಈ͕ӡ࣍ୈͰൃੜ͢Δ25
Asynchronous Callback/ Event DrivenLock ͱٯͷൃ͕࣌དྷͨ࣌ʹ callback ΛݺΜͰىͯ͜͠Β͏ (node.js ͕͜ͷϞσϧ)ྫ͑௨৴ Disk I/O ͷॲཧ݁ՌΛ callback Ͱड͚औΔΑ͏ʹ͠ɺcallback ͞ΕΔ·ͰผͷॲཧΛ࣮ߦ• callback ͷλΠϛϯάͰͷΈεϨου͕ΓସΘΔͨΊɺϚϧνεϨουͷෳࡶੑ͕ܰݮ͞ΕΔ• ͦͷΘΓ callback ͷ୯ҐͰ͔͠ॲཧ͕ΓସΘΒͳ͍ͨΊɺCPU ར༻ޮ fairness ඍົ• fairness CPU ͷ༗ޮ׆༻ͦΕ΄Ͳؾʹ͠ͳ͍͕ I/O ͙ͪ࣌ؒΒ͍༗ޮ׆༻͍ͨ͠ɺͱ͍͏χʔζ͖• ϓϩάϥϛϯάͷύϥμΠϜ͕ҟͳΔͨΊॾʑ͕ରԠ͍ͯ͠Δ͜ͱ͕ඞཁ• ίʔυ্͕͔ΒԼͱॱ൪ʹΒͳ͍, Ϋϩʔδϟ callback ͷཧղ͕લఏ (ಛʹσόοά࣌ʹ׳Ε͕ඞཁ)• ैདྷܕͷσόοΨͩͱͦΕΒͷঢ়ଶΛ͏ͷʹखֻ͕͔ؒΔ͜ͱ͕ଟ͠ (ϒϥβ JavaScript Ͱݦஶ)• ͦͦϥΠϒϥϦɾϛυϧΤΞ͕Ұ؏ͯ͠ callback ϕʔεͷ I/O ͳΓʹରԠ͍ͯ͠Δ͜ͱ͕ඞཁ26ϒϥβ JS node.js, winRT ɺҰ؏ͯ͠ callback ϞσϧͰඋ͞Ε͍ͯΔڥ͕͓͢͢Ί
Queueing / Pipelining• લஈ͔Β࣍ஈͱσʔλΛ͍ͯ͘͠• ֤ஈී௨ʹ࣮ͯ͠ queue ܦ༝Ͱܨ͙͚ͩͳͷͰ࣮͘͢͠όά͕গͳ͍• ஈʹ͚Δ͜ͱͰࣗવͱߏԽɾׂ౷࣏͞ΕΔޮ༻• queue ΛڬΉ͜ͱͰɺଟগͷͷϜϥ͕͋ͬͯ༡ΜͰ͠·͏εϨου͕ग़ͳ͍• ͱ͍֤͑ஈͷϖʔε͕ฏۉతʹҰக͠ͳ͍ͱɺॲཧ͕ͪग़ͯ͠·͏• queue ʹࡏ͢Δ͕࣌ؒ͋ΔͨΊɺϨΠςϯγ͕ॏཁͳ web ը໘ʹෆ͖• ݸผσʔλͷॲཧ࣌ؒΑΓεϧʔϓοτ͕ॏཁͳόον༻్ͱඇৗʹߴ૬ੑ• ؒʹڬΉ queue ϚϧνεϨουରԠͷͷΛ͏͜ͱ (Ͱͳ͍ͱ Queue ෦Ͱෆ߹)• Java: java.util.concurrent ҎԼͷίϨΫγϣϯΫϥε• Ruby: (Sized)Queue (require ‘thread’) or ͍ͬͦͷ͜ͱ Redis27Map Reduce ͜ͷҰछ
MessagingPipeline ߏ͕ࣗ༝ʹͳͬͨ൛, ॎԣແਚErlang (ϓϩάϥϛϯάݴޠ) Windows ͷ window message ͕͜ͷϞσϧͳΜͰͰ͖Δॊೈੑ͕͋Δ͕ɺ͋·Γࣗ༝ࣗࡏʹ͏ͱ:• ϝοηʔδ͕ࢥΘ͵ॴʹूதͯ͠ੑೳԼ…• ܦ࿏͕ෳࡶʹͳΔʹͭΕͯωοτϫʔΫߏͷอक͕େม…• ςετɾσόοά͕͍͠ɺԿ͔͋ͬͨ࣌ͷӨڹಡΈͮΒ͍…ͱ͍ͬͨհ͞Λ͏࣮͢͠Δ߹ɺωοτϫʔΫͷݟ͔ΒֶΔͱ͜Ζ͕େͳͷͰࢀߟʹ28
Immutable ObjectAtomic Reference, Hazard Pointerڞ༗σʔλΛݟͳͯ͘σʔλΛ࡞ΕΔ߹(DB ͔Βͷϩʔυ, ܭࢉ݁ՌͷΩϟογϡ)ʹ༗༻• σʔλΛҰ୴࡞ͬͨΒೋͱॻ͖͑ͳ͍ (ॻ͖͑ෆೳͳΦϒδΣΫτ, Immutable Object)• ॻ͖ΘΒͳ͍͔Βෆ߹ͷ৺͕શ͘ͳ͍ → հͳෆ߹όά͔Βͷղ์• Immutable Object ͷࢀরΛڞ༗͢ΔΑ͏ʹ͠ɺࢀরઌΛΓସ͑Δ͜ͱͰߋ৽͢Δ• ݹ͍൛ͷ Object Λࢀর͍ͯ͠ΔεϨουΛࢭΊͨΓ͠ͳ͍ → Lock ͷ᠘ʹϋϚΒͳ͍࠷৽σʔλ͕ଞͷεϨου͔Βݟ͑ΔΑ͏ʹͯ͠Δඞཁ͕͋ΔͷͰҙ:• Java, C# ͳΒΦϒδΣΫτͷࢀরΛ volatile ʹ͢Δ• C++11 ͳΒ memory_order_seq_cst ͔ memory_order_release/acquire ͳ atomic ૢ࡞Immutable Object Λෳݟʹߦ͘Α͏ͳઃܭཁҙ (Ͳ͏͍͏ॱংͰಡΈʹߦ͔͘ෆఆʹͳΔ)·ͨɺGC ͷແ͍ݴޠͰΦϒδΣΫτͷճऩʹ͕ඞཁ (→ Hazard Pointer Ͱݕࡧ)29
Local Variable, Thread Local StorageͦΕຊʹෳεϨουͰڞ༗͢Δඞཁͷ͋Δσʔλ͔Ͳ͏͔ྫ͑ը໘ͷϦΫΤετ 1 ͭ 1 ͭͷॲཧঢ়ଶΛෳεϨουͰڞ༗͢Δඞཁͳ͍ͷͰෳͷεϨουͰ୲ͯ͠ॲཧΛͨ͠Γಉ࣌ʹࢀর͢ΔσʔλҎ֎ɺͦͦෳεϨου͔Βݟ͑Δॴʹஔ͔ͳ͍ϙϦγʔ͕༗༻• ؔͷϩʔΧϧมɺϩʔΧϧมͷΈ͔ΒḷΕΔΦϒδΣΫτ• Thread Local Storage : ؔΛލ͍ͰΛอଘɺͨͩ͠εϨου͝ͱʹผ• TLS ʹσʔλ͕ஔ͖ͬͺͳ͠ʹͳΔ͜ͱͰϝϞϦফඅ͕ଟ͘ͳΓա͗ͳ͍͔ɺϦʔΫ͠ͳ͍͔ɺʹؾΛ͚ͭΑ͏30
ෆ߹ʹରॲ͢ΔͨΊͷΞϓϩʔνಉ࣌ʹσʔλʹ৮ΕΔεϨουΛݶఆ͢Δܥ (ฒྻ, ൺֱతສೳ)• Lock / Semaphore• Read-Write Lock• Optimistic Lock (CAS loop)• Asynchronous Callback / Event Driven• Queueing / Pipelining• Messaging• Immutable Object (Atomic Reference, Hazard Pointer)• Local Variable, Thread Local Storageͦͦڝ߹͠ͳ͍͔ΒେৎͩΑܥ (ߴฒྻ, ϝϦοτେ)31
Welcome to concurrentprocessing world !Next slide: Q & A session memo
Q & A memo (1/3)• Java Ͱ Pipelining ͢Δࡍʹɺpipeline ʹೖΕͨΦϒδΣΫτͷϑΟʔϧυʹvolatile Λ͚ͳ͍ͱ͍͚ͳ͍ʁ• No. Concurrent ͳίϨΫγϣϯͰ͋ΕɺίϨΫγϣϯʹΦϒδΣΫτΛೖΕΔ·Ͱૢ࡞ͷ݁Ռ͕ɺίϨΫγϣϯ͔ΒಡΈऔΔଆ͔ΒՄࢹͰ͋Δ͜ͱ͕༷ͱͯ͠نఆ͞Ε͍ͯΔ• https://docs.oracle.com/javase/jp/7/api/java/util/concurrent/package-summary.html ͷʮϝϞϦʔ߹ੑಛੑʯΛࢀর• ͨͩ͠ɺPipeline ʹͤΔΦϒδΣΫτ Immutable ʹ͢Δͷ͕҆શ• ෳεϨου͔ΒΞΫηε͞ΕΔͨΊ (Ұൠతͳ Pipeline ઃܭͰಉ࣌ʹΞΫηε͞Εͳ͍͕)33
Q & A memo (2/3)• ͜͜Ͱड़ΒΕ͍ͯΔख๏ϚϧνεϨουʹݶΒͳ͍ͷͰʁ• Yes, ΄ͱΜͲٛͷʮσʔλΛڞ༗͢Δฒߦॲཧʯશൠʹݴ͑ΔϊϋͰ͋Δ• ຊࢿྉʹ͓͚Δ ϚϧνεϨου ͷ࣮ࡍʹҙຯ͢Δͱ͜Ζ σʔλΛڞ༗͢Δฒߦॲཧશൠ• ΠϕϯτϞσϧ(࣮ thread 1 ຊ)ͷ node.js ͳͲʹݴٴ͍ͯ͠ΔͷͦͷͨΊ• ྫ͑ Ruby 2.0 Ͱ OS ଆͷ Copy-on-Write Λҙࣝͨ͠ GC ͷվળ(Bitmap Marking)͕͋ΓɺϚϧνϓϩηε͔ͩΒͱ͍ͬͯϑοτϓϦϯτ͕େ͖͍Θ͚Ͱͳ͍ͷͰ• fork લ͔Βͷϓϩηεͷಈ͖ͰݟΔͱ Immutable Object ύλʔϯΛݴޠॲཧܥ͕࣮ͯ͘͠Ε͍ͯΔͱݴ͑ɺσʔλΛڞ༗͢Δฒߦॲཧͱͯ͠ͷ࠷దԽ͕ߦΘΕͨঢ়ଶͰ͋Δ• σʔλΛڞ༗͠ͳ͍ฒߦॲཧ(Ϛϧνϓϩηεͱ͍͏දݱΛͨ͠)ͷඇޮ͕͞ղফ͞Εͨঢ়ଶ• ࠓճड़ͨഎܠख๏ɺͦ͏͍ͬͨOS ॲཧܥͷ͍ͬͯΔΛཧղ͢Δࡍͷࢀߟʹ• Compaction Ͱ͖Δ GC ͱ fork & CoW ͷ૬ੑ͕ݪཧతʹѱ͍͜ͱมΘΒͳ͍34
Q & A memo (3/3)• ϚϧνεϨουʹ͢Δ͔Ͳ͏͔ɺ͍ͭͲ͏அ͢Δ͔• ࠷ॳʹ࣮͢Δ࣌ͰʮͳͥϚϧνεϨου͔?ʯ(Slide 6) Ͱड़ͨಈػΛຬͨ͢߹• ·ͨෛՙࢼݧͳΓ࣮ӡ༻ͰϠό͍ʂͱͳͬͨ߹• ޙ͔ΒϚϧνεϨουԽ͢Δ߹ͲͷΑ͏ͳखΛଧ͔ͭ• Immutable Object ύλʔϯʹͰ͖Δͷ͢Δ• Pipeline ύλʔϯʹ͠ɺ֤ஈʹγϯάϧεϨουͳطଘίʔυΛԡ͠ࠐΉ• ίʔυ͕ڧ੍తʹׂ͞ΕΔ͜ͱʹΑΔϦϑΝΫλϦϯάޮՌಘΒΕΔ• ඞཁ࠷খݶͰͷϩοΫͷಋೖ (ϩοΫͷ᠘ʹཁҙ)• ͦΕμϝͳΒ࡞Γ͢• ࣮ࡍɺϚϧνεϨουʹ͢Δඞཁੑ͕ͳ͍ͳΒɺ͠ͳ͍ͷ͕࠷ળ• ͦ͏ݴ͍ͬͯΒΕͳ͍ঢ়گʹͳͬͨͱ͖ʹࠓճͷ͕ࢀߟʹͳΕ͍35