代表的なNsLock, MainActor, DispatchQueueについてまとめています
個人的な使い分けも整理しています
各種特徴
NSLock
基本的で簡易的に実装できる
ある処理が実行されている間に、特定の処理をロックすることで実現
func updateData() {
// 共有データへのアクセスを開始
lock.lock()
// このcritical sectionは、一度に一つのスレッドしか実行できません
sharedData += 1
print(sharedData)
// 共有データへのアクセスを終了
lock.unlock()
}
上記のようにlock()-unlock()で挟まれたコードブロックは、一度に一つのスレッドしか実行できなくなります
そのため安全にshareDataを更新することができます
NSLockはunlock()を忘れると、ロックかけっぱなしになるデッドロックに注意する必要があります
また待機中のスレッドの起動順は保証されません
MainActor
メインスレッドでserializeに実行することができます
@MainActorの宣言のみで、メインスレッドでの実行が保証されるため実装も容易です
ただしUIスレッドを占有してしまうので、何でもかんでも実装するのはよNGです
DispatchQueue
スレッドでserializeに実行される
キュー(列)で順番に処理されるため、タスクの順序が保障される
メインスレッドで実行されるmain queueと、メインスレッド外で実行できるgrobal queueがある
まとめ
各処理の使い分けはこんな感じでしょうか
NSLock
手動でロックの制御をする場合。DispatchQueueよりも細かくコードをブロックしたい時に使う。
ただしデッドロックのリスクがあるため、使う際は要注意
MainActor
UI更新やDB更新のようなメインスレッドで実行する必要がある処理に使用する
DispatchQueue
UIスレッド以外で非同期処理を行うときの一般的な手段として使う