5

mam właściwość @property NSLock *myLockJak zablokować NSLock na konkretnym wątku

I chcę napisać dwie metody:

- (void) lock 

i

- (void) unlock 

Te sposoby blokowania i odblokowywania myLock odpowiednio i muszą to zrobić bez względu na to, który wątek lub kolejka je wywołała. Na przykład wątek A mógł wywołać lock, ale kolejka B może być tą, która wywołuje unlock. Obie te metody powinny działać poprawnie bez zgłaszania, że ​​próbuję odblokować blokadę z innego wątku/kolejki, która je zablokowała. Dodatkowo muszą to zrobić synchronicznie.

Odpowiedz

23

Rzadko zdarza się, że NSLock jest właściwym narzędziem do pracy. Teraz jest o wiele lepsze narzędzie, szczególnie w przypadku GCD; więcej później.

Jak już zapewne wiesz z the docs, ale powtórzę dla tych, czytając razem:

Ostrzeżenie: klasa NSLock korzysta z POSIX wątki do wdrożenia jego zachowanie blokującą. Wysyłając wiadomość odblokowującą do obiektu NSLock, musisz mieć pewność, że wiadomość jest wysyłana z tego samego wątku, który wysłał początkową wiadomość blokującą. Odblokowanie blokady z innego wątku może spowodować niezdefiniowane zachowanie.

To bardzo trudne do wdrożenia bez zakleszczenia, jeśli próbujesz zablokować i odblokować na różnych wątkach. Podstawowym problemem jest to, że jeśli lock blokuje wątek, to nie ma możliwości, aby kolejny unlock kiedykolwiek uruchomił się na tym wątku, a Ty nie możesz unlock na innym wątku. NSLock nie dotyczy tego problemu.

Zamiast NSLock można zastosować te same wzory z dispatch_semaphore_create(). Można je bezpiecznie aktualizować w dowolnym wątku. Możesz zablokować za pomocą dispatch_semaphore_wait() i możesz odblokować za pomocą dispatch_semaphore_signal(). To powiedziawszy, ta nadal nie jest właściwą odpowiedzią.

Większość rywalizacji o zasoby najlepiej zarządzać za pomocą kolejki operacji lub kolejki wysyłkowej. Zapewniają one doskonałe sposoby równoległego obsługiwania pracy, zarządzania zasobami, czekania na zdarzenia, wdrażania wzorców producenta/konsumenta, a także wykonywania prawie wszystkiego, co wcześniej byś zrobił z NSLock lub NSThread. Bardzo polecam Concurrency Programming Guide jako wprowadzenie do tego, jak projektować za pomocą kolejek, a nie blokad.

Powiązane problemy