Re: Question about Threading
Re: Question about Threading
- Subject: Re: Question about Threading
- From: Laurent Michel <email@hidden>
- Date: Wed, 10 Aug 2005 16:35:50 -0400
On Aug 10, 2005, at 3:07 PM, James Bucanek wrote:
Chris Kane wrote on Wednesday, August 10, 2005:
I'm not saying the above example does this, just providing the
following warning...
Don't, however, try to solve the synchronization and "wait until the
background thread is done" by locking a lock in one thread which the
other thread unlocks. That invokes undefined behavior in the
underlying POSIX lock objects, and is a bad idea. I warn about this
because it is tempting to do because it seems simple. One should
never use mutex locks to implement "conditional waiting" is the
point; that is, never use -lock on a mutex in a "block until
something happens" sense, where the event is signalled by some other
thread (obviously, since the current thread is now blocked on the
lock) unlocking the previously locked lock.
Whoa, Chris. You're completely freaking me out! If I understand
what you wrote correctly, you're saying that if thread A gets a
lock on an NSLock, then thread B shouldn't release it? I've been
doing exactly this for donkey's years:
- Create and lock some result object
- Start a new thread with the calculation of that object
- New thread starts and will release the lock on the result
object when done
- Go do other stuff
- When I want the results, I request a second lock on the
result object.
- When I obtain the lock, I read the results.
I don't know any other way of accomplishing this. I can't have the
new thread create the initial lock on the result object, because as
soon as I start the thread my two threads are in a race condition
to make the first lock.
What other mechanism are you supposed to use to accomplish this?
I'm looking at NSConditionalLock, but it's not immediately obvious
to me how this solves the problem. I'm guessing that you're
advocating some kind of state machine where a double-handshake is
used to get the two threads sync'd up beyond the initial race
condition when the second thread is created but hasn't obtained any
locks yet. Is that the general idea, or am I completely mis-reading
all of this?
Does anyone have some example code?
You should use either semaphores or POSIX condition. The
NSConditionLock is, I believe a layer on top of posix conditions.
A counting semaphore would do the trick as follow: It counts the
number (0/1) of results available. It starts at 0. Then you create
the computation thread. Once the thread is done has has produced the
result it increments the semaphore. The main thread carries on and
when it wishes to access the result, it attempts to decrease the
semaphore.
A semaphore is a non-negative quantity. Any attempt to decrease it
past 0 cause the caller to block... So if the main thread attempts to
read the result right away, since the semaphore starts at 0, it will
block. Once the producer (computing thread) produces its result, it
increases the semaphore. If the main guy was blocking, it wakes up.
If the main guy has not attempted to pick up the result yet, the
semaphore becomes 1 and any attempt to pick up the result will not
block since the decrease will breing the semaphore back down to 0
(which is non negative).
POSIX conditions have the same expressive power as semaphore but are
a bit more flexible. Essentially, the idea with a condition is to
block a thread when a condition is false and have another thread wake
him up when the condition is true. Conditions works hand-in-hand with
mutex. (which explains my belief that NSConditionLock is a wrapper
around this).
Here is an example: a producer consumer "buffer" of size 1.
State: 2 boolean variables: ready and freeSpace
. initally ready = FALSE;
freeSpace = TRUE;
2 conditions:
- one to signal that space is free and can be used.
- one to signal that the result is available for pickup.
Consumer (the thread that picks up the result)
Mutex x;
lock(m);
while(!ready)
wait(readyCond,m);
ready = FALSE;
freeSpace = TRUE;
pick up result
freeCond.signal();
unlock(m);
Producer (the thread that produces the result: we could have >1
producer here!)
lock(m);
while(!freeSpace)
wait(freeCond,m);
freeSpace = FALSE;
ready = TRUE;
result = <some result>
readyCond.signal();
unlock(m);
Hope this helps
--
Laurent
_______________________________________________
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