On 03.10.2010 02:38, Caleb Clausen wrote:
> On 9/29/10, Robert Klemme<shortcutter / googlemail.com>  wrote:
>> Without going into too much detail I believe one flaw of your design
>> here is that you are not using thread synchronization but instead try to
>> explicitly start and stop threads and yield execution.  It may be that
>> this is causing your cores, but I really don't know.
>
> I agree that in general it's better to do this kind of thing using the
> appropriate synchronization data structures... however, I should
> expect that it is not possible to crash the ruby interpreter purely by
> writing ruby code, regardless of the presence of bugs in it. I don't
> know whether it is possible to actually achieve this level of
> reliability when dealing with threading code that contains race
> conditions, tho.

Absolutely agree.  But since 1.9.2 is pretty fresh I'd expect the more 
traditional code (proper thread sync) to be less likely to crash than 
obscure variants.

>> What I would do:
>>
>> 1. Use a condition variable to let all threads start at the same time.
> [snip]
>> lock.synchronize do
>>     start = true
>>     cond.signal
>> end
>
> Putting aside my prejudices against ConditionVariable, there is
> another problem with this: ConditionVariable#signal awakens only one
> thread waiting on the condvar. You'd want to use
> ConditionVariable#broadcast instead.

Right, sorry for mixing this up.

> But even then, there is a race
> condition; you're not guaranteed that all the threads have blocked
> waiting on the condvar. Some may still be running the code before that
> point, and they would end up never running to completion.

This is not true.  The only negative thing that would happen is that 
they would not start doing their work at the "same" time as the other 
threads.  Other than that they would do their work as the other threads.

> A counting
> semaphore could solve that, but ruby doesn't actually have one of
> those (sigh).
>
> Thread synchronization is a real PITA.

Well, your answer kind of confirms this. :-)

> I see now that the first line of ConditionVariable#broadcast is this:
>    # TODO: imcomplete
> So, maybe there's some kind of problem with it?
>
>> You can probably get away without the condition variable by just
>> acquiring the lock (lock.synchronize) in the main thread before you
>> create all threads and let all threads just synchronize with an empty block.
>
> I can't see any holes in this scheme, so it's probably the best idea.

Even then it could be that some threads execute code before the 
synchronize and thus not start concurrently with other threads. 
Frankly, for a test scenario I would not bother to try to let threads 
start really concurrently.  Unless there is huge preparation overhead I 
would simply create those threads and let them do their work.  There is 
no guarantee anyway that they can work in parallel because in a non 
realtime OS there are no guarantees as to when the scheduler decides to 
give CPU to threads.

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/