Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Condition variables and thread scheduling

Reply
Thread Tools

Condition variables and thread scheduling

 
 
Alex Young
Guest
Posts: n/a
 
      11-29-2010
I'm trying to understand how condition variables are supposed to work;
specifically, I've got this code:


# a.rb
require 'monitor'

def try
a = ""
a.extend(MonitorMixin)

cvar = a.new_cond

t1 = Thread.start do
a.synchronize do
cvar.wait
a << "b"
end
end

t2,t3 = [2,3].map{
Thread.start do
a.synchronize do
a << "a"
cvar.signal
end
end
}

[t2,t3,t1].each{|t| t.join}

return a
end


1000.times do |i|
output = try()
raise "Oops! (#{i} says #{output})" unless output == "aba"
end


This consistently fails like this on both jruby-1.5.1 and ruby-1.8.7:

$ ruby a.rb
a.rb:39: Oops! (220 says aab) (RuntimeError)
from a.rb:37:in `times'
from a.rb:37

That means that t1 was woken up after both t2 and t3, despite being
signaled to wake up by the first to execute, and it has no indication
that it was signaled twice.

I presume this is intentional behaviour (although it's a *little*
surprising), and the same thing happens if I use Mutex and
ConditionVariable instead of MonitorMixin, so is there any way to ensure
that the thread scheduling goes as [t2,t1,t3] *or* [t3,t1,t2], but never
[t2,t3,t1]?

--
Alex

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      11-29-2010
On Mon, Nov 29, 2010 at 10:51 AM, Alex Young <(E-Mail Removed)> wrote:
> I'm trying to understand how condition variables are supposed to work;
> specifically, I've got this code:
>
>
> # a.rb
> require 'monitor'
>
> def try
> =A0a =3D ""
> =A0a.extend(MonitorMixin)
>
> =A0cvar =3D a.new_cond
>
> =A0t1 =3D Thread.start do
> =A0 =A0a.synchronize do
> =A0 =A0 =A0cvar.wait
> =A0 =A0 =A0a << "b"
> =A0 =A0end
> =A0end
>
> =A0t2,t3 =3D [2,3].map{
> =A0 =A0Thread.start do
> =A0 =A0 =A0a.synchronize do
> =A0 =A0 =A0 =A0a << "a"
> =A0 =A0 =A0 =A0cvar.signal
> =A0 =A0 =A0end
> =A0 =A0end
> =A0}
>
> =A0[t2,t3,t1].each{|t| t.join}
>
> =A0return a
> end
>
>
> 1000.times do |i|
> =A0output =3D try()
> =A0raise "Oops! (#{i} says #{output})" unless output =3D=3D "aba"
> end
>
>
> This consistently fails like this on both jruby-1.5.1 and ruby-1.8.7:
>
> $ ruby a.rb
> a.rb:39: Oops! (220 says aab) (RuntimeError)
> =A0from a.rb:37:in `times'
> =A0from a.rb:37
>
> That means that t1 was woken up after both t2 and t3, despite being
> signaled to wake up by the first to execute, and it has no indication
> that it was signaled twice.
>
> I presume this is intentional behaviour (although it's a *little*
> surprising), and the same thing happens if I use Mutex and
> ConditionVariable instead of MonitorMixin, so is there any way to ensure
> that the thread scheduling goes as [t2,t1,t3] *or* [t3,t1,t2], but never
> [t2,t3,t1]?


Yes, this is intentional behavior. There are no guarantees with
regard to timing and order in which threads obtain the monitor. This
means especially that thread 2 and 3 can obtain any number of times
before thread 1 runs again.

Please note also that the intended usage of condition variables is
different: you obtain a lock then you loop while the condition is not
reached and then you continue. This is what you rather want if you
want to ensure alternation:

require 'monitor'

Thread.abort_on_exception =3D true

def try
a =3D ""
a.extend(MonitorMixin)
next_run =3D :b

cond_a =3D a.new_cond
cond_b =3D a.new_cond

t1 =3D Thread.start do
a.synchronize do
until next_run =3D=3D :a
cond_a.wait
end

a << "b"

next_run =3D :b
cond_b.signal
end
end

t2,t3 =3D [2,3].map do
Thread.start do
a.synchronize do
until next_run =3D=3D :b
cond_b.wait
end

a << "a"

next_run =3D :a
cond_a.signal
end
end
end

[t1,t2,t3].each{|t| t.join}

return a
end


1000.times do |i|
output =3D try()
raise "Oops! (#{i} says #{output})" unless output =3D=3D "aba"
end

Kind regards

robert


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

 
Reply With Quote
 
 
 
 
Alex Young
Guest
Posts: n/a
 
      11-29-2010
Robert Klemme wrote in post #964651:
> On Mon, Nov 29, 2010 at 10:51 AM, Alex Young <(E-Mail Removed)>
> wrote:
>>
>> Thread.start do
>> end
>> $ ruby a.rb
>> ConditionVariable instead of MonitorMixin, so is there any way to ensure
>> that the thread scheduling goes as [t2,t1,t3] *or* [t3,t1,t2], but never
>> [t2,t3,t1]?

>
> Yes, this is intentional behavior. There are no guarantees with
> regard to timing and order in which threads obtain the monitor. This
> means especially that thread 2 and 3 can obtain any number of times
> before thread 1 runs again.
>


That's what I thought, ok.

> Please note also that the intended usage of condition variables is
> different: you obtain a lock then you loop while the condition is not
> reached and then you continue. This is what you rather want if you
> want to ensure alternation:

<snip>

Perfect, thanks. I'll give that a try.

--
Alex

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Help with while condition OR condition Bill W. Ruby 13 05-09-2011 09:42 PM
passing messages between ruby thread and scheduling vincent Ruby 0 06-22-2005 03:57 AM
Condition outside loop or separate loop for different condition? - Java 12 06-15-2005 08:50 AM
weird delay of UDP server (seems to be thread-scheduling issue) chris guenther Ruby 0 04-10-2005 06:21 PM
ASP Thread Scheduling Anomalies Tony Proctor ASP General 6 03-16-2005 04:59 PM



Advertisments