[MacRuby-devel] Thread safety in apply example?
Joshua Ballanco
jballanc at gmail.com
Mon Jan 24 09:23:34 PST 2011
On Sat, Jan 22, 2011 at 12:57 AM, Charles Oliver Nutter <headius at headius.com
> wrote:
> I'm curious about this example in Queue#apply's rdoc:
>
> * gcdq = Dispatch::Queue.new('doc')
> * @result = []
> * gcdq.apply(5) {|i| @result[i] = i*i }
> * p @result #=> [0, 1, 4, 9, 16, 25]
>
> apply is said to issue the jobs in parallel, so this would be making
> concurrent updates to the @result array. Are simple arrays in MacRuby
> thread-safe?
>
Arrays in MacRuby are not inherently thread safe. However,
"Dispatch::Queue.new" creates a serial queue. So, there is an error in that
each invocation of the block will execute serially. If, instead, the example
had used "Dispatch::Queue.concurrent", then there would be a potential bug,
but the easiest way to work around that is:
gcdq = Dispatch::Queue.concurrent
@result = []
@result_q = Dispatch::Queue.new('@result_assignment_queue')
gcdq.apply(5) { |i| res = i * i; @result_q.async { @result[i] = res } }
p @result
There's also a mixin available in the Dispatch gem which abstracts away the
need for a serial queue for assignments by monkey-patching assignments to
all happen on a serial queue.
For those wondering about the advantages to this technique, it's worth
noting that GCD has a much lower overhead than more traditional methods of
parallelism. That said, if the calculation for each iteration is small, this
is not a useful technique. However, if the calculation for each iteration is
long or (more likely) non-deterministic -- as in waiting for an external
call or a remote connection -- then this can be a useful technique to
continue doing useful work while letting iteration complete in the
background.
Cheers,
Josh
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-devel/attachments/20110124/3a04b80c/attachment.html>
More information about the MacRuby-devel
mailing list