Condition variables and thread scheduling

Discussion in 'Ruby' started by Alex Young, Nov 29, 2010.

  1. Alex Young

    Alex Young Guest

    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/.
     
    Alex Young, Nov 29, 2010
    #1
    1. Advertising

  2. On Mon, Nov 29, 2010 at 10:51 AM, Alex Young <> 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/
     
    Robert Klemme, Nov 29, 2010
    #2
    1. Advertising

  3. Alex Young

    Alex Young Guest

    Robert Klemme wrote in post #964651:
    > On Mon, Nov 29, 2010 at 10:51 AM, Alex Young <>
    > 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/.
     
    Alex Young, Nov 29, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. -
    Replies:
    12
    Views:
    696
    Remon van Vliet
    Jun 15, 2005
  2. Tony Proctor

    ASP Thread Scheduling Anomalies

    Tony Proctor, Mar 2, 2005, in forum: ASP General
    Replies:
    6
    Views:
    269
    Tony Proctor
    Mar 16, 2005
  3. chris guenther
    Replies:
    0
    Views:
    112
    chris guenther
    Apr 10, 2005
  4. vincent
    Replies:
    0
    Views:
    166
    vincent
    Jun 22, 2005
  5. Bill W.
    Replies:
    13
    Views:
    294
    Phillip Gawlowski
    May 9, 2011
Loading...

Share This Page