Re: NSLock locking order;
Re: NSLock locking order;
- Subject: Re: NSLock locking order;
- From: Matt Budd (Madentec) <email@hidden>
- Date: Thu, 10 Nov 2005 14:18:54 -0700
Thanks Joseph and Shawn for the replies. I guess it comes down to the
fact that there is no inherent order, but it probably does a decent
job of assigning locks fairly.
Perhaps expanding on my exact situation might help. I have since
realized I don't need 3 threads, but instead have 2 threads (the main
thread and a worker thread). The worker thread loops through an array
of numbers and adds a certain amount to those number depending on the
direction. The main thread either changes the direction for each of
those numbers or adds more numbers (with an initial direction) to the
array. But basically, I don't want the worker thread to add to the
numbers if I am changing the direction or adding numbers. Here's some
more detailed psuedo-code (typed in Mail so don't mind any typos):
- (void)handleWorkerThread: (id)poPassedObject
{
NSAutoreleasePool *loThreadPool = [[NSAutoreleasePool alloc] init];
while (YES) {
NSAutoreleasePool *loLoopPool = [[NSAutoreleasePool alloc]
init];
[_oAllowedToAccumulate lock];
NSEnumerator *loNumberIterator = [_aoNumbers objectEnumerator];
NSMutableDictionary *lyNumber;
while ((lyNumber = [loNumberIterator nextObject]) != nil) {
[lyNumber setValue:
[NSNumber numberWithInt: (
[[lyNumber
valueForKey: @"number"] intValue]
+ [[lyNumber
valueForKey: @"direction"] intValue]
)
]
forKey: @"number"
];
}
[_oAllowedToAccumulate unlock];
[NSThread sleepUntilDate: [NSDate
dateWithTimeIntervalFromNow: 0.05]];
[loLoopPool release];
}
[loThreadPool release];
}
- (void)setDirection: (int)piDirection forNumber: (int)piIndex
{
//This is called on the main thread
[_oAllowedToAccumulate lock];
NSMutableDictionary *lyNumber = [_aoNumbers objectAtIndex:
piIndex];
[lyNumber setValue: [NSNumber numberWithInt: piDirection]
forKey: @"direction"];
[_oAllowedToAccumulate unlock];
}
- (void)addNumber: (int)piNumber
{
//This is called on the main thread
[_oAllowedToAccumulate lock];
[_aoNumbers addObject: [NSMutableDictionary
dictionaryWithObjectsAndKeys:
[NSNumber
numberWithInt: piNumber],
@"number",
[NSNumber
numberWithInt: +1],
@"direction",
nil
]
];
[_oAllowedToAccumulate unlock];
}
The problem is that if I call -setDirection:forNumber: or -addNumber:
from the mail thread, it might block if the worker thread is busy
accumulating. And at that point, I know that there is a state change
(either a direction or cardinality change), so I want the accumulator
to block the next time it goes to acquire the lock. But this code
doesn't guarantee this...it is possible here for the main thread to
block in either of the latter two methods, and then the worker thread
gets swapped in and re-locks the lock before the main thread can.
Any suggestions? I can't use conditional locks, because I end up with
the same scenario...in the main thread I'd have to lock it first to
unlock it with a condition and then in the worker thread I'd have to
lock when the condition was "no state change pending". But then if I
did get that lock in the worker thread, the main thread would block
before it could lock it to unlock it with the condition "state change
is pending", so it would be possible for the same scenario...
- Matt
On Nov 10, 2005, at 1:15 PM, Joseph Kelly wrote:
NSLock is based on pthreads, whose docs often mention the fact that
there are no guarantees as to which thread will acquire a lock. If
you need to synchronize your threads, then NSConditionLock is your
new friend:
Main Thread:
[_oLock initWithCondition:THREAD_A_WORK];
...
Thread A:
[_oLock lockWhenCondition:THREAD_A_WORK];
...
[_oLock unlockWithCondition:THREAD_B_WORK];
Thread B:
[_oLock lockWhenCondition:THREAD_B_WORK];
...
[_oLock unlockWithCondition:THREAD_C_WORK];
Thread C:
[_oLock lockWhenCondition:THREAD_C_WORK];
...
[_oLock unlockWithCondition:THREAD_A_WORK];
On Nov 10, 2005, at 10:37 AM, Matt Budd (Madentec) wrote:
Hello all,
Say I have three threads competing for the same NSLock. Here's
some small psuedo code:
Thread A, B, and C (just with different "<stuff>")
--------------------------------------------------------------
while (YES) {
[_oLock lock];
<stuff>
[_oLock unlock];
[NSThread sleepUntilDate: [NSDate
dateWithTimeIntervalSinceNow: 0.5]];
}
So lets say thread A got the the lock first, and then then got
swapped out while doing "<stuff>". Then thread B blocks attempting
to acquire the lock. Then thread C runs and also blocks attempting
to acquire the lock. Then we get back to thread A and it finishes
its "<stuff>", unlocks the _oLock, and sleeps for half a second.
Is there any order to who will get to acquire the lock next? Does
thread B get it because it is queued up somewhere in the
foundation's NSLock class that it is first? Or is there a
possibility that thread A might finish its sleep and loop around
and obtain the lock again? Or does thread C have a chance?
Thanks for any info...
- Matt
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden