はじめに
時々出てきて、雰囲気で使っている言葉にスレッドがある。await関数内などでこのスレッドに関する処理がいい感じに非同期処理を実現してくるらしく、こんな感じでも扱えてしまうところがカプセル化の力かと感謝するしかない。
ただ、甘えてばかりだと力もつかないので、雰囲気で受け取っていたスレッドへの浅い理解を深め、知ったかぶりから脱したい
スレッドから思い浮かぶワード
- プロセスよりも小さい単位で、スレッドの集まりがプロセスとも言う
- JavaScriptはシングルスレッドで動作し、イベントループで
- Unityは、UIまわりをプログラムから変更する際、メインスレッドで行う必要がある
- スレッドセーフならマルチスレッドでも安心
- 掲示板のこともスレ(スレッド)って言うよね
シングル? メイン? セーフ? スレッドに付随するワードが多くて、いろんな
文脈で出てくるからスレッドはややこしくなってそう。一つ一つ確認していきたい
スレッドの辞書的な意味
まず、スレッド単体の意味はこれ
スレッド(thread)とは、コンピュータプログラムにおいて特定の処理を行うための一貫性のある命令の流れのことであり、プロセッサ利用の最小単位[1]。プロセスは少なくとも1つ以上のスレッドを含む。一般的に各プロセスには独立した仮想アドレス空間が割り当てられるが、プロセス内のスレッド群はアドレス空間を共有する。そのためプログラムを実行するときのコンテキスト情報が最小で済み、同じプロセス内でスレッドを切り替える際はアドレス空間の切り替えが不要となるので、切り替えが高速になる[2]。 (wikipedia)
語源としては糸のことらしい
原義は縒り糸を構成している糸のうちの一本や、筋状の物体のうちの一本の筋などを意味する英語threadである。ここから派生し、同時進行する事象のうちの一つをあらわすようになった。 (wikipedia)
糸とシングルスレッド
この例えで言うと、糸の端と端はプログラミングの文頭から文末に対応し、処理を上から下に順番で実行し、最後にスレッドは消える。糸の先端と先端の様に、ひと繋ぎになっている。シングルスレッドというのは、この糸が一本だけあって端から端まで他の糸が絡む子ことがない様子を表すのだろう。
一直線に上から下といっても、whileループやif文があれば一直線にならないと思ったが、whileの時は意図が途切れずその場で回るし、ifだと曲がるだけとイメージすれば、やはり途切れない糸というのは納得できた
マルチスレッドの中のメインスレッド
メインスレッドはマルチスレッドがあることで出てくる言葉で、メインから枝分かれするサブスレッドがあるため、区別するためプロセスの開始から終了までを処理するスレッドのことをメインスレッドと呼ぶのだろう。マルチスレッドの中の一番太い糸(thread)をメインスレッドと呼ぶのだろう。
メインスレッドの途中からGitのブランチみたいに枝分かれすることがあるのが、シングルスレッドに対するマルチスレッドの違いということになりそう。
Gitでもブランチ切った後に合流しようとする時のコンフリクトが発生することがあるが、マルチスレッドも糸を増やせば絡まることがあるという話なのだろう。
スレッドセーフ
複数のスレッドからメソッドやプロパティにアクセスされても問題が起きない、もしくは複数スレッドからアクセスされることを想定し排他制御が行われているようなクラスやメソッドを「スレッドセーフ」と呼ぶ
排他制御 で引っかかった。競合が発生しないようDBのようにロックするのはそれはそうかと思いつつ、ロックしている間にアクセスがる場合処理が進まないわけで、裏で別の処理をするためにスレッドを分けたのに排他制御で待たされたら、結局パフォーマンス上がらないじゃん! という疑問が自然と浮かぶ。
こういう本末転倒なことが容易に発生しうるのでマルチスレッドは難しいと言われるのだろう。
安易にマルチスレッドに手をつけるとパフォーマンスがそれほど向上しないにも関わらず、ログで追えないようなバグが発生するだけということになりかねない、というのが今の所の理解
おわりに
UnityでUniTaskを使って非同期処理を書いている時、UIを操作しようと意した時に「メインスレッドから呼ばれていない」的なエラーに出会した。
おまじない的にObserveOnMainThread()を足して凌いでいたりしたが、これはUnityが描画を行うメインスレッド以外のスレッドでUI操作を行うとスレッドセーフで無くなるから例外として扱っている、と解釈できるのか? 何はともあれ理解に一歩近づけた気がする。
参考