On Aug 19, 2008, at 9:22 AM, Daniel M. wrote:
b = Thread.new do
This code never starts thread b. It seems that thread a blocks all
other threads once it runs (though its priority is lowered), even the
main thread.
If I put a sleep command into the thread a loop, thread b starts, but
the problem remains, since then thread b blocks all others from
running.
that code looks completely non-deterministic to me and i’ve had
similar issues many times in the past. i think the fundamental error
is mistaking the creation of a thread for scheduling it. i’ve used
the following pattern many times to force my code to know that a
thread has started processing before continuing:
cfp:~ > ruby186 a.rb
starting thread a
starting thread b
count1: 4580083
count2: 44732
cfp:~ > ruby187 a.rb
starting thread a
starting thread b
count1: 4394267
count2: 37032
cfp:~ > cat a.rb
require ‘thread’
q = Queue.new
count1 = count2 = 0
a =
Thread.new do
puts “starting thread a”
q.push Thread.current
loop { count1 += 1 }
end
a = q.pop # wait for the thread to start
a.priority = -1
b =
Thread.new do
puts “starting thread b”
q.push Thread.current
loop { count2 += 1 }
end
b = q.pop # wait for the thread to start
b.priority = -2
sleep 1 #=> 1
Thread.critical = 1
puts “count1: #{count1}”
puts “count2: #{count2}”
i’m sorry that i cannot test this on cygwin so i’m not sure it’s the
issue. but to me it simply looks like non-deterministic code. in
fact, even the code above has a race condition, i only force the
program to ensure each thread calls puts - there is nothing to make
sure that stdout has been flushed or that the increments have run in
the loop. to do that i think you’d need something like this
cfp:~ > cat a.rb
require ‘thread’
q = Queue.new
count1 = count2 = 0
a =
Thread.new do
STDERR.puts “starting thread a”
loop do
count1 += 1
q.push Thread.current if count1 == 1
end
end
a = q.pop # wait for the thread to start
a.priority = -1
b =
Thread.new do
puts “starting thread b”
q.push Thread.current
loop do
count2 += 1
q.push Thread.current if count2 == 1
end
end
b = q.pop # wait for the thread to start
b.priority = -2
Thread.critical = 1
puts “count1: #{count1}”
puts “count2: #{count2}”
cfp:~ > ruby186 a.rb
starting thread a
starting thread b
count1: 19297
count2: 28490
cfp:~ > ruby187 a.rb
starting thread a
starting thread b
count1: 17435
count2: 24603
i’d be curious how that fairs on cygwin. notice that the sleep is not
required with the queues.
regards.
a @ http://codeforpeople.com/