スレッド間で繰り返し同期を取る必要がある場合、今までは AutoResetEvent を使っていたが、こちらの記事に「CountdownEvent の方が、オーバーヘッドが小さい」と書かれていた。
そうだったのか!
昔どこかのサンプルコードを見て AutoResetEvent を使っていたけど、他の手段との比較検討はしたことなかったなぁと思い、実際に CountdownEvent と処理速度を比べてみた。
処理速度の結論
処理速度について結論から言うと、AutoResetEvent より CountdownEvent のほうが速い。
そもそも
同期に使えるクラスはたくさんあり、MS 公式にまとめられている。そのうち、
- AutoResetEvent……スレッドをシグナル状態になるまで待機させる。単一の待ちスレッドが解放された後、自動的にリセットされる。
- CountdownEvent……スレッドをカウントダウンが 0 になるまで待機させる。複数のスレッドからのシグナルで 1 つ以上のスレッドのブロックを解除できる。
また、AutoResetEvent はスレッド解放後に自動的にリセットされる(何もしなくても再び待機させられる)ので、セットし忘れてスレッドがスルーしてしまうバグや、セットのタイミングでブロックできないケースが発生するバグの軽減につながり、安心感は高い。
速度比較
機能的な違いは横に置いておいて、処理速度のみに注目して比較。コードは GitHub に上げておいた。
メインスレッドとサブスレッドでそれぞれブロックし合うこと 500 万回(メインとサブがそれぞれブロックするので同期回数は 1,000 万回)、その所要時間を計測した。

- AutoResetEvent:22,031 ミリ秒
- CountdownEvent:578 ミリ秒
となり、CountdownEvent のほうが 40 倍近く速いという結果になった。
まとめ
同期回数 1,000 万回で 20 秒程度の差が出たので、100 万回でも秒単位の差が出ることになる。短時間で 100 万回レベルの同期を行う場合は、CountdownEvent を選択する方が良いと思う。
自分のプロジェクトだとそこまで頻繁に同期するわけではなく(数分間で 1 万回程度、つまり 20 ミリ秒程度の差異)、速度差は誤差程度なので、安心感のある AutoResetEvent を使い続けるかもしれない。