Question

I´m getting this error using NSLock which I tried to circumvent by using unlockWithCondition (using NSConditionLock), but regardless I get the same result:

* Break on _NSLockError() to debug. * -[NSLock unlock]: lock ( '(null)') unlocked from thread which did not lock it.

I´m not sure if it´s bad, but what I´m doing is this:

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];

So the section "..shared code.." can execute. I don´t understand why i´m getting this error.

Can anyone explain what I´m doing wrong? It´s look like it should work perfectly.

Was it helpful?

Solution

I think you're trying to use locks as semaphores here. Locks are meant to stop the background thread and the main thread from accessing something simultaneously. Hence, the thread holding the lock must release (unlock) it too.

If you want the background thread to wait for something to happen on the main thread, use semaphores.

Use GCD semaphores for nice and easy semaphores: https://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

OTHER TIPS

If you are doing your HTTP requests on NSURLConnection or similar and trying to unlock in the delegate, you need to be careful where you create and initiate the NSURLConnection from, as it should return to that thread, unless you explicitly use scheduleInRunLoop:mode to put it on another thread or run loop.

If you are certain that you're locking on the main thread, you should be unlocking on that thread. To get back there, you can use either performSelectorOnMainThread:withObject:waitUntilDone: callback or GCD to call back on the main thread using:

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

With your unlocks in the ... space. You could use dispatch_sync() instead if you need to know the unlocks have completed before moving on.

However, using NSConditionLock, as you'd indicated you'd already tried is the solution. However, you still need to do the lock on the retrieval thread, not on the main thread. The condition will be guarded by your -unlockWithCondition: using a specific condition, so it won't unlock prior to the retrieval thread marking it as ready.

So, in your main thread, launch the retrieval threads. In each retrieval thread, -lock and then proceed to retrieve the data, then -unlockWithContidition:. In the consumer thread, use -lockWhenCondition and you should be fine.

The key is, though, that you have to lock and unlock on the same thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top