IOS SDK - сообщение NSLock: "разблокировано из потока, который не заблокировал его"
Я получаю эту ошибку, используя 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 ответа
Я думаю, что вы пытаетесь использовать замки в качестве семафоров здесь. Блокировки предназначены для того, чтобы остановить фоновый поток и основной поток от одновременного доступа к чему-либо. Следовательно, нить, удерживающая блокировку, должна также разблокировать (разблокировать) ее.
Если вы хотите, чтобы фоновый поток ожидал, что что-то произойдет в основном потоке, используйте семафоры.
Используйте семафоры GCD для удобных и простых семафоров: https://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
Если вы выполняете свои HTTP-запросы на NSURLConnection или аналогичном и пытаетесь разблокировать его в делегате, вам нужно быть осторожным, когда вы создаете и инициируете NSURLConnection, так как он должен вернуться в этот поток, если вы явно не используете scheduleInRunLoop:mode
поместить его в другой поток или запустить цикл.
Если вы уверены, что блокируете основной поток, вы должны разблокировать этот поток. Чтобы вернуться туда, вы можете использовать либо performSelectorOnMainThread:withObject:waitUntilDone:
обратный вызов или GCD для обратного вызова в главном потоке, используя:
dispatch_async(dispatch_get_main_queue(), ^(void) {
...
});
С вашими разблокировками в... пространстве. Вы могли бы использовать dispatch_sync()
вместо этого, если вам нужно знать, что разблокировка завершена, прежде чем двигаться дальше.
Однако, используя NSConditionLock
, как вы указали, вы уже попробовали это решение. Тем не менее, вам все равно нужно сделать блокировку в потоке поиска, а не в основном потоке. Условие будет охраняться вашим -unlockWithCondition:
используя определенное условие, поэтому он не будет разблокирован до того, как поисковый поток пометит его как готовый.
Итак, в вашем основном потоке запустите поисковые потоки. В каждой поисковой теме -lock
а затем приступить к извлечению данных, затем -unlockWithContidition:
, В потребительской ветке используйте -lockWhenCondition
и ты должен быть в порядке.
Ключ в том, что вы должны заблокировать и разблокировать один и тот же поток.