【Swift】DispatchSemaphoreの使い方!非同期処理を待機する方法

【Swift】DispatchSemaphoreの使い方!非同期処理を待機する方法

この記事からわかること

  • SwiftDispatchSemaphore使い方
  • 非同期処理待機して実行する方法
  • タイムアウト設けるには?

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

公式リファレンス:Combine Framework

環境

DispatchSemaphoreとは?

公式リファレンス:DispatchSemaphore

DispatchSemaphore複数のスレッドから操作される非同期処理を一元管理して同時にリソースを参照しないようにすることができるクラスです。仕組みとしては内部的にカウンターを保持しており、そのカウントが0の時は他の非同期処理は実行しないようにします。

DispatchSemaphoreクラスをインスタンス化する際に同時に実行できる非同期処理数を指定します。

// セマフォの初期カウントを1に設定
let semaphore = DispatchSemaphore(value: 1)

そして非同期処理を開始する際waitメソッドを実行し、非同期処理を終了する際signalメソッドを実行します。waitメソッドを実行すると内部カウンターが-1され、signalメソッドを実行すると内部カウンターが+1されます。

semaphore.wait()   // -1
// 非同期処理
semaphore.signal() // +1

カウンターが0になっている間は他の非同期処理を開始することができません。そのため非同期処理が終了したタイミングで適切にカウンターを戻さないと動作しなくなってしまうので注意してください。

実装サンプル

例えば以下のような非同期処理が2つあるとします。

print("開始")
DispatchQueue.global().async {
    print("Task 1 start" )
    sleep(4)
    print("Task 1 end")
}

DispatchQueue.global().async {
    print("Task 2 start")
    sleep(2)
    print("Task 2 end")
}

これをそのまま実行するとそれぞれの非同期処理は並列に動作するので出力は以下のようになります。

出力

開始
Task 1 start
Task 2 start
Task 2 end   // 開始から2秒後
Task 1 end   // 開始から4秒後

DispatchSemaphoreを導入してみると2つの非同期処理は直列に実行されるようになります。

// セマフォの初期カウントを1に設定
let semaphore = DispatchSemaphore(value: 1)

print("開始")

DispatchQueue.global().async {
    // セマフォを待機
    semaphore.wait()
    print("Task 1 start" )
    sleep(4)
    print("Task 1 end")
    // セマフォのシグナル
    semaphore.signal()
}

DispatchQueue.global().async {
    // セマフォを待機
    semaphore.wait()
    print("Task 2 start")
    sleep(2)
    print("Task 2 end")
    // セマフォのシグナル
    semaphore.signal()
}

出力

開始
Task 1 start
Task 1 end   // 開始から4秒後
Task 2 start
Task 2 end   // 開始から6秒後

タイムアウトを設ける

DispatchSemaphoreにはタイムアウトを設けることが可能です。このタイムアウトは指定した秒数の間非同期処理が開始にならなかった場合にタイムアウトを検出できます。

let result = semaphore.wait(timeout: .now() + 5) // 5秒間のタイムアウトを設ける

if result == .timedOut {
    print("Timeout occurred")
} else {
    // セマフォのシグナル
    semaphore.signal()
}

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index