Hi all,
I've started to use GCD in my projects and I found myself using a certain
pattern that I now realize isn't actually thread safe. The goal is to write a
thread-safe lazy accessor without using locks, @synchronized, or an atomic
property. At first I thought that
- (SomeObjType) foo
{
__block SomeObjType foo = nil;
dispatch_sync(queue,
^{
// retrieve bah
if (nil == bah)
{
// compute and store bah
}
foo = bah;
});
return foo;
}
would do it. Here, bah is some resource that may be changed by multiple threads
and queue is a serial GCD queue defined as a static variable in the class where
this accessor is defined. The queue is not any of the global queues, but is
created by the class.
I see two problems with this pattern.
The first is that if the method gets invoked already in the queue's automatic
thread, there will be a deadlock. That's easy to fix, by wrapping the dispatch
call into a function that tests queue against the currently executing queue and
simply executes the block when they coincide.
The second problem is that the pattern isn't actually thread safe. If two
threads (that aren't the automatic thread of the queue) enter the accessor, two
blocks will be enqueued serially. The two threads will then block, waiting for
their blocks to finish executing.
So far so good but when the first block finishes, it could happen that the
first thread blocks until the second block finishes, at which time the foo
value computed by the first block will have been replaced by the value computed
by the second block, since foo is shared among all blocks that captured it.
Thus, when the first thread resumes, it will report the wrong foo value.
So, what is the correct pattern to write a thread-safe lazy accessor without
using locks, @synchronized, or an atomic property?
Thanks in advance.
WT_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]