2013-03-13 7 views
13

In Apple-docs, heißt es:Wie erstelle ich einen Deadlock in Grand Central Dispatch?

Wichtig: Sie sollten die dispatch_sync nie anrufen oder dispatch_sync_f Funktion aus einer Aufgabe, die in der gleichen Warteschlange ausgeführt wird, dass Sie Planung sind an die Funktion zu übergeben. Dies ist besonders wichtig für serielle Warteschlangen , bei denen ein Deadlock garantiert ist, die jedoch auch für gleichzeitige Warteschlangen vermieden werden sollten.

Wie schreiben Sie den Code, um genau dies zu tun?

+0

Sie mögen Beispiel-Code, die Deadlock erzeugt? – Vladimir

+0

Ja bitte, zum Lernen – BlackMouse

+1

Siehe auch [diese Frage] (http://stackoverflow.com/questions/10330679/how-to-dispatch-on-main-queue-synchronous-without-a-deadlock) für ein realistisches Beispiel das kann leicht zum Stillstand kommen. – zoul

Antwort

20

Eine beabsichtigte Deadlock auf einer bestimmten Warteschlange:

dispatch_queue_t queue = dispatch_queue_create("my.label", DISPATCH_QUEUE_SERIAL); 
dispatch_async(queue, ^{ 
    dispatch_sync(queue, ^{ 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    }); 

    // this will never be reached 
}); 

Es ist klar, dass hier die äußeren und inneren Blöcke auf der gleichen Warteschlange arbeitet. Die meisten Fälle, in denen dies auftreten wird, sind an Orten, wo es weniger offensichtlich ist, welche Warteschlange der Anrufer von dispatch_sync bearbeitet. Dies tritt normalerweise in einem (tief) verschachtelten Stapel auf, in dem Sie Code in einer Klasse ausführen, die ursprünglich in einer bestimmten Warteschlange gestartet wurde, und aus Versehen rufen Sie dispatch_sync in derselben Warteschlange an.

+0

Wenn in Deadlock ... sollte die Benutzeroberfläche nicht reagieren? – BlackMouse

+2

@ user1251004 Nur wenn die Hauptwarteschlange blockiert wird. –

+2

In diesem Beispiel ist nur die erzeugte 'queue' blockiert. Die Hauptwarteschlange läuft glücklich weiter. –

7

Einfacher Code, Deadlock erstellt:

dispatch_queue_t q = dispatch_queue_create("deadlock queue", DISPATCH_QUEUE_SERIAL); 

NSLog(@"1"); 
dispatch_async(q, ^{ 
    NSLog(@"2"); 
    dispatch_sync(q, ^{ 
     NSLog(@"3"); 
    }); 
    NSLog(@"4"); 
}); 
NSLog(@"5"); 

Protokollausgabe:

1 
5 
2 

Hier interner Block geplant ausgeführt wird auf serieller Warteschlange q aber es kann nicht ausgeführt werden, bis aktuelle Block wird beendet, während Der aktuelle Block wiederum wartet intern, um zu beenden, wie wir es synchron nannten.

4

Der einfachste Weg ist, um dispatch_sync auf der aktuellen Warteschlange zu blockieren:

dispatch_sync(dispatch_get_current_queue(), ^{}); 

Dies blockiert, wenn die aktuelle Warteschlange eine serielle Warteschlange ist, zum Beispiel die Hauptwarteschlange.

0

In neuester Swift Syntax:

let queue = DispatchQueue(label: "label") 
queue.async { 
    queue.sync { 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    } 
    // this will never be reached 
} 
Verwandte Themen