mutexとsemaphoreはもはや同期"プリミティブ"ではない

スレッドの教科書にはスレッド同期のプリミティブとしてmutexとsemaphoreが挙げられることが多い。
が、これらはもはや最初に教えるべきプリミティブではないだろう、というはなし。(必要な場面があることには変わりないと思うが)


時代は昭和後半、OSのマルチスレッドが「タイムスライス」だけで実現されていた時代というのがあった。
CPUはシステムにひとつしか存在せず、あるスレッドが他のスレッドに作業を進めてもらうためには、自分のスレッドがCPUを解放する必要があった。

その時代においては、「他のスレッドの完了を待つ」ということは、すなわち、「コンテキストスイッチする」、ということであり、mutex/semaphoreは、そのように設計され、それらが同期"プリミティブ"として教科書にのるようになった。
(ほんまか?誰もが、「mutexがあればsemaphoreて実装できんじゃね?」ぐらい考えるだろ。なのに何故semaphoreが"プリミティブ"としてあらゆる教科書で説明されるのか…)


しかし…時代は流れ、一般家庭の奥様が使う京速コンピュータにまで富士通の世界最速(Linpack基準て)プロセッサVenusが載る時代になり、もはや「他のスレッドの完了待ち」は、「コンテキストスイッチ」と同等ではなくなってしまった。

各スレッドはそれぞれ独自に計算リソースを持っており、自分のスレッドがわざわざ計算リソースを手放さなくても、他のスレッドがタスクを完了することが可能になったからだ。


コンテキストスイッチにはコストがかかるため、もし、自分のスレッドの手元にすぐに実行できる他のタスクがあった場合、コンテキストスイッチせずに、すぐに実行できるタスクを実行したほうが、トータルのスループットが向上する可能性がある。
性能向上を考えるうえで、「コンテキストスイッチしない」というのが、設計上の選択肢として挙がるようになったわけだ。

すなわち、現代においては、「スレッドがブロックすること」が前提の同期オブジェクトは、特殊な状況下でのみ使える同期オブジェクトであり、"プリミティブ"と呼んでよいほどプリミティブなものではないのである。



というわけで、今の時代になっても、「マルチスレッドとはミューテクスとセマフォがくっついてできあがるのです」とかの説明を見ると「うぎゃー」という気分になってしまうのだった。


さて、では、現代においては、何を同期プリミティブとすべきだろうか。

僕が考えるに、「そのアーキテクチャにおけるアトミックな操作」というのを同期プリミティブとすべきだと思う。

そんで、それをもとに、「小さなアトミック操作をつかって、大きなアトミック操作をつくる」というのを実現する方法が一般的にある、と、そういう感じ。

x86ならば、cmpxchg と lock 付きの演算があって、
PowerPC なら、lwarx, stwarx(だったかな?)というreservation付きロードストアがある。
個人的にはPowerPCのほうがよくできてる…x86はRead-Write期間中バスロックしないといけないけど、PowerPCはWrite期間中だけバスロックしてればよい…と思うのだが、それはいいか、x86に実装されるSTMはPowerPCのに近くなるのかな。というかx86にSTMが実装されるってどこで見たんだ夢の中か?


なんか文章考えるのがめんどうになってきたので適当だが。
「アトミックな操作」という視点で考えると、ああ、そういえば、最近実装されてるプログラミング言語ってそういう観点で定義されてる仕様があったなぁ。という気がしてきて、ちょっとJavaとかC#とかC++0xとか仕様見たほうがいいな。


ともかく、これからの時代は、「アトミックな操作はなんであるか?」と「小さなアトミック操作を使って大きなアトミック操作を実現する」という点を教科書に載せるべきだと思う。
Lock-Freeなアレコレとか、まさに、「小さなアトミック操作を使って大きなアトミック操作を実現する」であると思うし。
というかそれなんてSTM。