ニートが学ぶ非同期処理 その4

はいどーも力尽きそうなニートですこんばんは。
今回の記事では「他のスレッドの処理と同調」させる処理をやってみたいと思います。

スレッド間での同調ってなに

例えばワーカースレッドが3つあるとします。
この3つのスレッドは一定のタイミングで同時に実行されることが望ましいとします。
これが「他のスレッドの処理と同調」するという意味です。
で、具体的にUnityだとどんなときに使うんだと言われれば……ウーン。
ちょっとよくわかりません。
複数のスレッドを起動して同調させたいことって、ぶっちゃけあんまりないような……。
いや僕が思いつかないだけで、超複雑な処理とかだとあるんですかね……。
バグの温床になりそうで僕はあんまり使いたくないような……。

とにもかくにもよくわかりませんが、本の中で紹介されているのでチマチマ進めてみます。

ポーリングして同調する

非同期処理に限らず、ポーリングして状態をチェックする処理を書いたことは誰でも一度くらいはあると思います。
というわけでポーリングして同調するバージョンをドン。

プログラムを実行すると、最初に3つのスレッドが開始されます。
その後、キーを押すたびにフラグのON/OFFを切り替えます。
この切り替えたものをDoWorkの中でポーリングし、3つのスレッドで同調させます。

ですがポーリングしている分、余分な処理が走っています。
また、ポーリングの間隔を100ミリ秒ごとにしているため、最大で100ミリ秒遅れて同調します。
ちょっと使いにくいですね。

イベント待機ハンドルを利用して同調する

先ほどのポーリングは若干使いにくいということが判明しました。
次はイベント待機ハンドルを利用して同調させてみます。
コードをドン。

ShouldDoWorkというポーリング用のプロパティの代わりに、WaitHandleというプロパティを宣言しています。
これがイベント待機ハンドルです。
スレッドを起動するときにWaitHandleの参照をDoWorkメソッドに引数で渡しておいて、シグナルを受信するまでスレッドをブロックしておきます(今回の場合だと別に引数で渡す必要ないですけど)。
こうすると、シグナルを送信すると次のループで

この行が実行されることになります。
ポーリングするよりもはるかにレスポンスがよくなりますね。

バリアを使って同調させる

お次はバリアを使った同調です。
バリアはバリアに参加しているスレッドの数だけシグナルが送信されるまで、そのスレッドを止める機能を持っています。
また、バリア通過後に実行したいコールバック関数も登録できます。
便利そうですが今までと全く同じ動きをさせるのは苦労しそうだったので、とりあえず「ずっとコンソールログを出力し続ける」ことにしました。
というわけでコードをドン。

バリアがうまく働いて、3つのスレッドが合流するまで待機してくれているのがわかるかなと思います。
しかしこういうコード、Unityで見かけませんね……?

終わりに

同調って一体何に使えばいいのかいまいちわかりませんでしたが、理屈は理解できました(多分)。
今一番知りたいのがいわゆるlockなので、そろそろ出てこないかな~と思いつつ本記事を終了したいと思います。

ほなそんな感じでまた。

フォローする