web-dev-qa-db-ja.com

Swiftのmain.syncでDispatchQueueがクラッシュする

このクラッシュが発生する理由を教えてください。

スレッド1:EXC_BAD_INSTRUCTION(code = EXC_I386_INVOP、subcode = 0x0)

これで

DispatchQueue.main.sync {print( "sync")}

これは私のコードです。

    override func viewDidLoad() {
    super.viewDidLoad()


    print("Start")
    DispatchQueue.main.async {
        print("async")

    }
    DispatchQueue.main.sync {
        print("sync")
    }
    print("Finish")
}

@ sankalap、Dispatch.mainは、すべての操作を実行する単一のスレッドを持つシリアルキューです。このキューで "sync"を呼び出すと、スレッドで現在実行されている他のすべての操作がブロックされ、記述したものは何でもsync内でコードブロックを実行しようとします。これにより、「デッドロック」が発生します。

9
Rohi

メインキューで同期関数を呼び出さないでください

メインキューで同期機能を呼び出すと、キューがブロックされ、キューはタスクが完了するのを待機しますが、キューが原因でタスクを開始することさえできないため、タスクは完了しませんすでにブロックされています。 deadlockと呼ばれます。

2つ(場合によってはそれ以上)のアイテム(ほとんどの場合、スレッド)は、お互いが完了または別のアクションを実行するのを待ってスタックする場合、デッドロックと呼ばれます。 1つ目は2つ目が終了するのを待っているため、終了できません。しかし、2つ目は、1つ目が終了するのを待っているため、終了できません。

ただし、注意が必要です。 syncを呼び出して、すでに実行している現在のキューをターゲットにするとします。これにより、デッドロック状態が発生します。

ディスパッチバリアを使用して作業を追跡する場合、またはクロージャによって処理されたデータを使用する前に操作が完了するのを待つ必要がある場合は、同期を使用します。

同期を使用するタイミング

タスクが完了するまで待つ必要がある場合。 F.e.一部の関数/メソッドが二重に呼び出されないようにする場合。 F.e.同期があり、完全に終了するまで二重に呼び出されないようにしています。 DIFFERENTキューで何かが行われるのを待ってから、現在のキューで作業を続ける必要がある場合

同期vs.非同期

GCDを使用すると、タスクを同期的または非同期的にディスパッチできます。

同期関数は、タスクが完了すると、呼び出し元に制御を返します。

非同期関数はすぐに戻り、タスクを実行するように命令しますが、タスクを待機しません。したがって、非同期関数は、現在の実行スレッドが次の関数に進むのを妨げません。

7
Sid Mhatre

Apple documentation 実行時dispatch_sync現在使用しているキューでコードがクラッシュします。

この関数を呼び出して現在のキューをターゲットにすると、デッドロックが発生します。

7
justintime