IOS SDK - сообщение NSLock: «разблокировано из потока, который не заблокировал его» - PullRequest
3 голосов
/ 01 марта 2012

Я получаю эту ошибку, используя NSLock, которую я пытался обойти, используя unlockWithCondition (используя NSConditionLock), но независимо от этого получаю тот же результат:

* Сбой _NSLockError ()отлаживать.* - [NSLock unlock]: блокировка ('(null)') разблокирована из потока, который не заблокировал его.

Я не уверен, что это плохо, но что яЯ делаю так:

new Thread:
[lockA lock];//waiting unlock
[lockB lock];//waiting unlock
..shared code..
[lockA unlock];
[lockB unlock];

in Main Thread:
//Do two HTTP request.

//when request respond, I unlock the locks in respective threads with [lockA unlock];
[lockB unlock];

Таким образом, раздел ".. общий код .." может выполняться.Я не понимаю, почему я получаю эту ошибку.

Может кто-нибудь объяснить, что я делаю неправильно?Похоже, это должно работать идеально.

Ответы [ 2 ]

6 голосов
/ 05 марта 2012

Я думаю, вы пытаетесь использовать замки здесь как семафоры.Блокировки предназначены для того, чтобы остановить фоновый поток и основной поток от одновременного доступа к чему-либо.Следовательно, поток, удерживающий блокировку, должен также освободить (разблокировать) ее.

Если вы хотите, чтобы фоновый поток ожидал, что что-то произойдет в основном потоке, используйте семафоры.

Используйте семафоры GCDдля красивых и простых семафоров: https://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

1 голос
/ 01 марта 2012

Если вы выполняете свои HTTP-запросы на NSURLConnection или аналогичном и пытаетесь разблокировать его в делегате, вам нужно быть осторожным, когда вы создаете и инициируете NSURLConnection, поскольку он должен вернуться в этот поток, если вы явно не используете scheduleInRunLoop:mode чтобы поместить его в другой поток или цикл выполнения.

Если вы уверены, что блокируете основной поток, вам следует разблокировать этот поток.Чтобы вернуться туда, вы можете использовать либо performSelectorOnMainThread:withObject:waitUntilDone: обратный вызов, либо GCD для обратного вызова в главном потоке, используя:

  dispatch_async(dispatch_get_main_queue(), ^(void) {
       ...
    });

С вашими разблокировками в ... пробел.Вместо этого вы могли бы использовать dispatch_sync(), если вам нужно знать, что разблокировка завершена, прежде чем двигаться дальше.

Однако, используя NSConditionLock, как вы уже указали, вы уже пытались решить эту проблему.Тем не менее, вам все равно нужно сделать блокировку в потоке поиска, а не в основном потоке.Условие будет защищено вашим -unlockWithCondition: с использованием определенного условия, поэтому оно не будет разблокировано до того, как поисковый поток пометит его как готовый.

Итак, в вашем основном потоке запустите поисковые потоки.В каждом потоке поиска -lock, а затем приступайте к извлечению данных, затем -unlockWithContidition:.В потребительской ветке используйте -lockWhenCondition, и с вами все будет в порядке.

Однако ключ в том, что вы должны блокировать и разблокировать в одной и той же цепочке.

...