9

Ich habe eine Serie Absende-Warteschlange erstellt mit:dispatch_async vs dispatch_sync Ausführungsreihenfolge

dispatch_queue_t serialQueue = dispatch_queue_create("com.unique.name.queue", DISPATCH_QUEUE_SERIAL); 

Ich mag diese serielle Warteschlange verwenden Thread-Sicherheit für Klasse Zugang zu gewährleisten, während automatisch Arbeit tut asynchron, dass muss nicht zurück zum aufrufenden Thread.

- (void)addObjectToQueue:(id)object 
{ 
    dispatch_async(serialQueue, ^{ 
     // process object and add to queue 
    }); 
} 

- (BOOL)isObjectInQueue:(id)object 
{ 
    __block BOOL returnValue = NO; 
    dispatch_sync(serialQueue, ^{ 
     // work out return value 
    }); 
    return returnValue; 
} 

Wenn ich die addObjectToQueue nennen: Methode, rufen Sie sofort die isObjectInQueue: Methode, sind sie garantiert in der gleichen Reihenfolge ausgeführt werden, oder wird/könnte die isObjectInQueue erste ausführen?

Mit anderen Worten, verarbeitet dispatch_async genau dasselbe wie dispatch_sync (Blockierung des Blocks sofort), außer dass der aufrufende Thread nicht blockiert wird?

Ich habe ähnliche Fragen mit Antworten in beide Richtungen gesehen, also bin ich auf der Suche nach einer endgültigen Antwort, vorzugsweise mit Apple-Dokumentation gesichert.

+2

"Wenn ich die addObjectToQueue: -Methode aufruft, dann rufe ich sofort die isObjectInQueue: -Methode auf, werden sie garantiert in der gleichen Reihenfolge ausgeführt, oder wird die isObjectInQueue zuerst ausgeführt?" Wenn Sie das fragen, meinen Sie wahrscheinlich "Können wir nach dem Objekt fragen, bevor es zur Warteschlange hinzugefügt wurde?". Denn offensichtlich laufen 2 Methoden so ab, dass sie aufgerufen werden, wenn sie auf demselben Thread aufgerufen werden. – krafter

Antwort

13

Wird garantiert, dass sie in der gleichen Reihenfolge ausgeführt werden?

Ja.

Wird/könnte die isObjectInQueue zuerst ausgeführt werden?

Ja.

Der Grund für das Ja zu beiden Antworten ist, dass Sie Threading berücksichtigen sollten. Aus diesem Grund verwenden Sie vermutlich die serielle Warteschlange. Sie machen den Zugriff auf diese Warteschlange threadsicher.

Grundsätzlich werden die Blöcke in der Reihenfolge ausgeführt, in der sie in die serielle Warteschlange eingereiht werden. Das ist 100% garantiert. Wenn jedoch mehrere Threads auf diese Weise hämmern, kann ein Thread zuerst hineingelangen, um etwas aus der Warteschlange zu lesen, bevor ein anderer Thread die Chance hatte, es hinzuzufügen.

In anderen Worten, mit Ausnahme dispatch_async genau die gleichen wie dispatch_sync (Scheduling des Blockes sofort) auszuführen, dass sie den aufrufenden Thread nicht blockiert sind?

Das stimmt. In beiden Fällen wird der Block der Warteschlange hinzugefügt. Es wird sofort hinzugefügt. dispatch_sync wartet nur darauf, dass der Block vor der Rückkehr beendet wird, während dispatch_async sofort zurückkehrt.

+2

Richtig; oder, um summieren zu können, werden Blöcke in einer seriellen Warteschlange in der Reihenfolge ausgeführt, die hinzugefügt wurde, und diese Reihenfolge wird nur deterministisch sein, wenn Sie "dispatch_async()/dispatch_sync()" von einem einzigen Thread ausführen. Wenn Sie mehrere Threads benötigen und eine Bestellung benötigen, müssen Sie einen Synchronisierungsmechanismus bereitstellen. Sie werden wahrscheinlich einen "Frische" -Indikator für den Rückgabewert von "isObjectInQueue:" benötigen, da dies wahrscheinlich in einer gleichzeitigen Umgebung schnell die Gültigkeit verlieren kann. I.e. Nebenläufigkeit ist schwer. – bbum

+0

Obwohl diese Diskussion alt ist, möchte ich sie wieder aufleben lassen, um einige Momente zu klären. 1. "Kann/konnte die isObjectInQueue zuerst ausgeführt werden? Ja." Andrew fragt, ob ** METHODS ** in zufälliger Reihenfolge ausgeführt werden könnten, die nacheinander aufgerufen werden, und nicht innerhalb von dispatch_async. aber: 2. Er meint wahrscheinlich selbst blockt. :). Kann dennoch ein Block vor dem anderen ausgeführt werden, wenn er zuletzt in der seriellen Warteschlange hinzugefügt wurde? ** "dispathc_async - Sendet einen Block für die asynchrone Ausführung in einer Dispatch-Warteschlange und kehrt sofort zurück. Aufrufe an diese Funktion werden immer sofort nach dem Senden des Blocks zurückgegeben." ** – krafter

2

Ich denke, Ihre Frage ist, wird der Hauptthread weiter ausgeführt, während dispatch_async noch die Warteschlange ausgeführt wird? Ich gehe davon aus, dass dies nicht nötig wäre, denn das würde eine ausdrückliche Erwähnung verdienen. Wenn überhaupt, fand ich dies in dispatch_async.3 was vermuten lässt, ist dies der Fall:

Konzeptionell dispatch_sync() ist eine bequeme Wrapper um dispatch_async() mit dem Zusatz eines Semaphore für Fertigstellung des Blocks zu warten, und ein Wrapper um den Block, um seine Fertigstellung zu signalisieren.

Und in der Tat, wenn Sie den Quellcode für dispatch_async in queue.c folgen Sie werden sehen, dass der Block auf dem Vordergrund der Warteschlange gestellt wird, und erst danach kehrt die Ausführung zu dem Code, die dispatch_async genannt. Wenn also die Warteschlange seriell ist, werden dispatch_async gefolgt von dispatch_syncaus demselben Thread die Blöcke in der Reihenfolge anordnen.

Weil dispatch_sync blockieren wird, bis der Block (und alle Blöcke zuvor in einer seriellen Warteschlange) ausgeführt werden, dann wäre Ihr Code richtig. isObjectInQueue: meldet korrekt, wenn das zuvor hinzugefügte Objekt in der Warteschlange ist.

bearbeiten:

- (void)addObjectToQueue:(id)object 
{ 
    dispatch_barrier_async(_queue, ^{ 
     // process object and add to queue 
    }); 
} 

- (BOOL)isObjectInQueue:(id)object 
{ 
    __block BOOL returnValue = NO; 
    dispatch_sync(_queue, ^{ 
     // work out return value 
    }); 
    return returnValue; 
} 

weil Ausführung jedes Verfahren an einer beliebigen Stelle für einen anderen Thread verschoben werden kann: auf einer Multithread-Umgebung ich den Code wie oben schreiben.

+0

Lesen Sie die Dokumentation dispatch_barrier_async. Wenn Sie eine selbst erstellte serielle Warteschlange verwenden, entspricht das Verhalten dem Befehl dispatch_async. Ist das korrekt? – Andrew

+0

Ja. Der obige Code setzt die Verwendung einer gleichzeitigen Warteschlange für eine Multithread-Umgebung voraus, da das Serialisieren von Lesevorgängen ein sinnloser Roadblock wäre. Bei einer seriellen Warteschlange werden jedoch keine Blöcke gleichzeitig ausgeführt, auf die die Barriere angewendet werden soll. Daher entspricht ein dispatch_barrier_async einem dispatch_async. – Jano

+1

'dispatch_barrier_async()' tut nichts in einer seriellen Warteschlange, weil per Definition alle vorherigen Blöcke in der Warteschlange zum Zeitpunkt der Ausführung des barriered-Blocks ausgeführt werden. Es wirkt sich nur auf gleichzeitige Warteschlangen aus. – bbum

Verwandte Themen