ロックフリー性の証明について
http://www.slideshare.net/kumagi/lock-free-safe?next_slideshow=1
とか過去に自分で書いておきながら、その当時の自分の認識が甘かった事もあるのでここに一度書き出しておく。
Lock-Freeは「ロックを使わない事」ではない
STMの事をもってしてLock-Freeと呼んでる文脈はいっぱいあるけれど、STMの実装にロックを使う事は一般的だし、それは正しい専門用語で言う所のLock-Freeとは呼ばない。
Lock-Freeとは「どんなスケジューリングが為されようともどれかの操作が進行する」という進行保証(Progress Guarantee)を表している。
スケジューリング?
マルチコアCPUでもシングルコアCPUでも、OSは実行中のプログラムを任意のタイミングで強制的に一時停止させて他のプログラムにCPUリソースを割り当てる事ができる*1。実行中スレッドからのOSによるCPUの引き剥がし・割り付けの事を並行プログラムの世界ではスケジューリングと呼ぶ。
シングルCPUコアの環境でついうっかりC言語あたりで無限ループを記述してもkillできるのはこの仕組みのお陰である。
Lock-Freeの進行保証について
スケジューラの立場からLock-Freeというのを解釈し直すと「どんなスケジューリングを行っても絶対に進行してしまう」アルゴリズムであって、Lock-Freeであることを証明するためには「考えうる限り最悪のスケジューリングを行った場合に、アルゴリズム側が何らかの操作を実現するまでに必要なクロック数の上限が無限でない」という事を示せば良い。
例えばシンプルなLock-Free Stackの場合、
- t個のスレッドで実行している
- スケジューラはpushもpopも1つでも実行させないよう最悪ケースのスケジュールを行おうとする
という状況にて
- headポインタのアドレスPを読むのにaクロック(有限)
- mallocにbクロック(有限)
- mallocしたメモリ領域Qk*3に必要なデータを書き込むのにcクロック(有限)
- P→QkのCASを試みるのにdクロック(有限)
- スケジューラはCASを失敗させたいのでCAS実行の直前で他のスレッドにCPU時間を割り当てる
- ↑の1〜5の動作をt個のスレッド全部の分繰り返す
- スケジューラはどのスレッドにCPU時間を割り当ててもP→QkのCASを実行しようとしているスレッドばかり
- t個のスレッドのうちどれかが必ずCAS成功する。スケジューラは t * (a + b + c + d)クロックで投了
- t * (a + b + c + d)は有限なのでこのアルゴリズムには進行保証がある
というようにLock-Free性(=進行保証)を証明できる。
Wait-Freeに関してはまた気が向いたら書く。