discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: thread question


From: Nicola Pero
Subject: Re: thread question
Date: Mon, 31 Dec 2001 14:56:47 +0000 (GMT)

> >   if (aLock == nil)
> >     {
> >       [globalLock lock];
> >       if (aLock == nil)
> 
> Hey ! we already know that aLock is nil !

No - we don't :-) - it's a multithreading world ... 

when multiple threads are executing that code, the way richard wrote it is
the correct one (better, it is the standard way of writing code which
works :-)

as an example of why the second check for aLock == nil, consider the
following thread scheduling example - 

Consider the first thread to reach these statements. aLock if nil.  The
first thread locks the globalLock.  Then goes on into creating aLock.

Now imagine that, while it's creating aLock, the thread is put into hold,
and another thread is given opportunity to execute.  The second thread
reaches the first check that aLock is nil.  aLock is still nil because it
has not yet been assigned (the first thread is still stuck somewhere
between the alloc and init).  So the second thread goes on.  It stops on
the [globalLock lock] because globalLock is taken by the first thread.

Now the first thread starts again.  It completes the creation of aLock,
and assigns it, then frees the globalLock and exits.  The second thread
can now enter the critical region ... with aLock != nil.  So, unless there
is a second check there that aLock is not nil, the second thread will
create aLock again, leaking the first one - and possibly causing more
problems by replacing the first aLock with a different aLock at some later
point ... imagine that the first thread had already locked aLock to do
something ... now the second thread replaces aLock with a different one
... more mess to come.

Summing up simply, the first check that aLock != nil is unreliable (or
better, it's reliable in checking that aLock != nil, but it's unreliable
in checking that aLock == nil), being outside the critical region where
the transition between aLock == nil and aLock != nil is made, while the
second one is the real check, because it's inside the critical region.  
The use of the first check is to make the code faster, because after aLock
has been created and is != nil, nothing will be executed - in particular,
the time-consuming locking of globalLock is not made at all - so the code
will not incur any thread-locking overhead.

I'm sorry if my quick explanation is not particularly well exposed - look
on the net for documentation on the double-checked locking pattern -
you'll certainly find a lot of good explanations of it.  It's just a
standard trick.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]