• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag
 

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Question about Threading
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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
References: 
 >Re: Question about Threading (From: James Bucanek <email@hidden>)

  • Prev by Date: Re: Addressing Relationships in awakeFromInsert
  • Next by Date: Re: Addressing Relationships in awakeFromInsert
  • Previous by thread: Re: Question about Threading
  • Next by thread: Re: Question about Threading
  • Index(es):
    • Date
    • Thread