为什么Ruby中的ConditionVariable不能按预期工作?

时间:2014-05-21 13:17:46

标签: ruby multithreading mutex condition-variable

我在理解Mutex和Condition变量如何在Ruby中工作时遇到了问题。 这是我的代码:

mutex = Mutex.new
cv = ConditionVariable.new

Thread.new  {
  puts 'First: Hello'

  cv.signal
}

 Thread.new  {
  cv.wait(mutex)

  puts 'Second: Hello'

}

Thread.new  {
  cv.wait(mutex)

  puts 'Third: Hello'
}

sleep 1

,结果是

First: Hello

我尝试使用cv.broadcast,但它没有改变任何东西。此外,我试图删除第三个线程,使其仅适用于线程,它也没有改变任何东西。那么,有人可以解释如何让两个线程等到另一个线程发出信号吗?

2 个答案:

答案 0 :(得分:1)

  1. 您需要在互斥锁(mutex.synchronize do ... end
  2. 的同步块内部工作
  3. 如果第一个线程首先运行,它可能会在其他线程wait之前完成,因此它们不会获得信号。
  4. signal唤醒一个线程,所以其他线程也应该在完成唤醒下一个线程时发出信号
  5. 因此,尝试将代码更改为以下内容:

    mutex = Mutex.new
    cv = ConditionVariable.new
    
    Thread.new  {
      sleep 1
      mutex.synchronize do
        puts 'First: Hello'
    
        cv.signal
      end
    }
    
    Thread.new  {
      mutex.synchronize do
        cv.wait(mutex)
    
        puts 'Second: Hello'
        cv.signal
      end
    }
    
    Thread.new  {
      mutex.synchronize do
        cv.wait(mutex)
    
        puts 'Third: Hello'
        cv.signal
      end
    }
    
    sleep 1
    

答案 1 :(得分:1)

经过一段时间的挣扎,我已经明白了问题所在。所有关于条件变量锁定的全部内容。如果我的代码是正确的,我不会,但它显示顺序运行。

cv = ConditionVariable.new
mutex = Mutex.new

mutex2 = Mutex.new
cv2 = ConditionVariable.new

mutex3 = Mutex.new
cv3 = ConditionVariable.new

mutex4 = Mutex.new
cv4 = ConditionVariable.new

mutex5 = Mutex.new
cv5 = ConditionVariable.new

mutex6 = Mutex.new
cv6 = ConditionVariable.new



Thread.new do
  mutex.synchronize {
    puts 'First: Hi'
    cv.wait(mutex)
    puts 'First: Bye'
    #cv.wait(mutex)
    cv.signal
    puts 'First: One more time'
  }

end

Thread.new do
  mutex.synchronize {
    puts 'Second: Hi'
    cv.signal
    cv.wait(mutex)
    puts 'Second:Bye'
    cv.signal
  }

  mutex2.synchronize {
    puts  'Second: Starting third'
    cv2.signal

  }
end

Thread.new do
  mutex2.synchronize {
    cv2.wait(mutex2)
    puts 'Third: Hi'
  }

  mutex3.synchronize {
    puts 'Third: Starting forth'
    cv3.signal
  }
end

Thread.new do
  mutex3.synchronize {
    cv3.wait(mutex3)
    puts 'Forth: Hi'
  }

  mutex4.synchronize {
    puts 'Forth: Starting fifth'
    cv4.signal
  }
end

Thread.new do
  mutex4.synchronize {
    cv4.wait(mutex4)
    puts 'Fifth: Hi'
  }

  mutex5.synchronize {
    puts 'Fifth: Starting sixth'
    cv5.signal
  }
end

Thread.new {
  mutex5.synchronize {
    cv5.wait(mutex5)
    puts 'Sixth:Hi'
  }
}

sleep 2