Common Lisp処理系拡張の探求 SBCLのマルチスレッドサポート
Common Lisp 処理系拡張の探求
SBCLのマルチスレッドサポート
Lisp Meet Up #29
About Me
- κeen
- @blackenedgold
- Github: KeenS
- 渋谷のエンジニア
- Lisp, ML, Shell Scriptあたりを書きます
CLのマルチスレッド
bordeaux-threads
- 色々な処理系のマルチスレッドサポートの抽象レイヤー
- デファクトスタンダード
- スレッド
- ロック
- コンディションヴァリアル
SBCLのマルチスレッド
SBCLのマルチスレッド
- スレッド
- スレッド内エラー
- アトミック操作
- CAS
- 排他制御(ロック)
- セマフォ
- コンディションヴァリアル
- バリア
- キュー
- メールボックス
- ゲート
- frlock
アトミック操作
アトミック操作
複雑な動作は同じデータに並行に動かすと壊れうる
[var = 1]
[incf] | [decf]
[1]<-------|
| |------>[1]
[2]--->[var = 2] |
| |
[var = 0]<--[0]
アトミック操作
atomic-{incf, decf}
- 動作出来る場所が限られている
atomic-{pop, push, update}
- CASプロトコルを実装していればどこでも
CASプロトコル
- compare and swap
- アトミック操作の基本中の基本
- ハードウェアレベルのサポート
- ざっくり言うと並行版setf
(cas place old new env)
- もし
place
がold
に等しければnew
を代入
- もし
(defun (cas foo) (old new))
cas
版のsetf
定義
- 他にも
setf
相当の機能は揃ってる
CASプロトコル
(defvar *foo* nil)
(defun (cas foo) (old new)
(cas (symbol-value '*foo*) old new))
キュー
- 普通のキュー
- スレッドセーフ
enqueue
,dequeue
が基本操作dequeue
が多値で、ブロックしない- 空なら第二値がnilになる
メールボックス
- キューとほぼ同じ
- スレッドセーフ
send-message
,recieve-message
が基本操作recieve-message
はブロックする- タイムアウトも設定出来る
recieve-message-no-hangはdequeue
と同じ挙動recieve-pending-messages
もある
ゲート
- 複数のスレッドが1つのイベントを待つ時に使う
wait-on-gate
,open-gate
,close-gate
が基本操作
[gate (closed)] [T1] [T2] [T3]
| | | |
| wait | | |
|<----------------+----+
| | . .
| open | . .
[gate (opened)]<--+ . .
+---------------->+--->+
go | |
V V
frlock
- Fast Read Lock
- またの名をRead-Write Lock
- Read Lockは多重に取れる。Write Lockは1つしか取れない。
- 基本操作は
frlock-read
とfrlock-write
- 普通のlockと違って複数のReadが速くなる
まとめ
- SBCLのマルチスレッドサポートはbordeaux-threadsよりもリッチ
- 処理系の独自サポート面白い
- 処理系に依存してしまってもいいんじゃないだろうか
Common Lisp 処理系拡張の探求
SBCLのマルチスレッドサポート
Lisp Meet Up #29