Shared memory with "mutex" and NSCondition on iPhone
What I need to do : In order开发者_如何学编程 to avoid global variable, I have a Singleton class containing an array. This array will be accessed by two different threads :
- 1) the first one will be the main thread and will have to add objects into this NSMutableArray from time to time. - 2) another thread is looping (while TRUE) and try to empty the array (when it contains something)My idea was (and what i did so far):
in my singleton class, i have my NSMutableArray (list
) and a NSCondition (conditionLock
).
[[sharedSingleton conditionLock] lock];
[[sharedSingleton list] addObject:obj];
[[sharedSingleton conditionLock] signal];
[[sharedSingleton conditionLock] unlock];
I want to block the object so that it doesn't get empty when I try to put objects in it. (shared memory protection). Once the object has been put into the array, I signal the other thread. If i understood it right, this is kind of increasing a counter, like with a semaphore right ? The signal is telling the other Thread "there is an object, go on".
What the second thread is doing:
while (YES) {
[[sharedRequest conditionLock] lock];
[[sharedRequest conditionLock] wait];
RequestLauncher * req = [[RequestLauncher alloc] initWithGenericsObject:[[sharedRequest list] objectAtIndex:0]];
[req performSelectorOnMainThread:@selector(Launch)
withObject: nil
waitUntilDone:YES];
[[sharedRequest list] removeObjectAtIndex:0];
[[sharedRequest conditionLock] unlock];
}
So i guess my problem is that I Lock and then wait for the signal, but all Apple example are in that order. This code seems to work when I'm adding one object in my main thread. However, when I want to add more than one, it gets blocked around the Lock.
EDIT
I tried something different, but the behavior was not the one expected :
while (YES) {
[[sharedRequest conditionLock] lock];
[[sharedRequest conditionLock] wait];
GenericsObject * obj = [[sharedRequest list] objectAtIndex:0];
[[sharedRequest list] removeObjectAtIndex:0];
[[sharedRequest conditionLock] unlock];
RequestLauncher * req = [[RequestLauncher alloc] initWithGenericsObject:obj];
[req performSelectorOnMainThread:@selector(Launch) withObject: nil waitUntilDone:YES];
}
Like this, I was unlocking the NSMutableArray so that the mainThread was able to add objects.
The second thread invokes a method on the main thread and waits until done the method in the condition lock. It would cause DEADLOCK. RequestLauncher is not able to be invoked in the second thread?
I finally got the answer.
I'm more use to C Multitasking, explaining the confusion here !
Basically, the code was almost good. What I thought signal was doing is that increasing the value of "a semaphore" so that if one Thread was signaling 5 times, the other Thread would pass the wait condition 5 times as well. Not at all.
My code in the first Thread was good (i.e)
[[sharedSingleton conditionLock] lock];
[[sharedSingleton list] addObject:obj];
[[sharedSingleton conditionLock] signal];
[[sharedSingleton conditionLock] unlock];
Following Apple exemple in that page that page , here is what I did
[[sharedRequest conditionLock] lock];
while ( ! ([[sharedRequest list] count] >0) ) {
[[sharedRequest conditionLock] wait];
}
GenericObjects * obj = [[sharedRequest list] objectAtIndex:0];
[[sharedRequest list] removeObjectAtIndex:0];
[[sharedRequest conditionLock] unlock];
RequestLauncher * req = [[RequestLauncher alloc] initWithGenericsObject:obj];
[[appDel queue] addOperation:req]; // appDel is an instance of the application delegate, and where queue is an instance of NSOperationQueue
Hope that might help someone !
精彩评论