5

ich eine Eigenschaft haben @property NSLock *myLockWie ein NSLock auf einem bestimmten Thread sperren

Und ich möchte zwei Methoden schreiben:

- (void) lock 

und

- (void) unlock 

Diese Methoden sperren und entsperren myLockund Sie müssen dies tun, unabhängig davon, welcher Thread oder welche Warteschlange sie aufgerufen hat. Zum Beispiel könnte Thread A lock genannt haben, aber die Warteschlange B könnte unlock sein. Beide Methoden sollten ordnungsgemäß funktionieren, ohne zu melden, dass ich versuche, eine Sperre aus einem anderen Thread/einer anderen Warteschlange, die sie gesperrt hat, zu entsperren. Darüber hinaus müssen sie dies synchron tun.

Antwort

23

Es ist selten, dass NSLock das richtige Werkzeug für den Job ist. Es gibt jetzt viel bessere Werkzeuge, besonders mit GCD; später mehr.

Wie Sie wahrscheinlich schon von the docs wissen, aber ich werde für diejenigen wiederholen Mitlesen:

Achtung: Die NSLock Klasse verwendet POSIX-Threads seine Sperrverhalten zu implementieren. Wenn Sie eine Entsperrungsnachricht an ein NSLock-Objekt senden, müssen Sie sicherstellen, dass die Nachricht von demselben Thread gesendet wird, der die ursprüngliche Sperrnachricht gesendet hat. Das Entsperren einer Sperre aus einem anderen Thread kann zu einem nicht definierten Verhalten führen.

Das ist sehr schwer ohne Deadlocking zu implementieren, wenn Sie versuchen, auf verschiedenen Threads zu sperren und entsperren. Das grundlegende Problem ist, dass, wenn lock blockiert den Thread, dann gibt es keine Möglichkeit für die nachfolgende unlock jemals auf diesen Thread laufen, und Sie können nicht unlock auf einem anderen Thread. NSLock ist nicht für dieses Problem.

Anstatt NSLock können Sie die gleichen Muster mit dispatch_semaphore_create() implementieren. Diese können sicher in jedem beliebigen Thread aktualisiert werden. Sie können sperren mitund Sie können entsperren mit dispatch_semaphore_signal(). Das heißt, diese immer noch ist normalerweise nicht die richtige Antwort.

Die meisten Ressourcenkonflikte werden am besten mit einer Operationswarteschlange oder einer Dispatchwarteschlange verwaltet. Diese bieten hervorragende Möglichkeiten, parallel zu arbeiten, Ressourcen zu verwalten, auf Ereignisse zu warten, Erzeuger-/Verbrauchermuster zu implementieren und ansonsten fast alles zu tun, was Sie in der Vergangenheit mit einem NSLock oder NSThread gemacht hätten. Ich empfehle die Concurrency Programming Guide als eine Einführung in das Design mit Warteschlangen statt Sperren.