【问题标题】:Why ConditionVariable in Ruby does not work as expected?为什么 Ruby 中的 ConditionVariable 不能按预期工作?
【发布时间】:2014-05-21 13:17:45
【问题描述】:

我无法理解 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,但它并没有改变任何东西。此外,我尝试删除第三个线程并使其仅适用于线程,它也没有改变任何东西。那么,有人能解释一下如何让两个线程等待另一个线程发出信号吗?

【问题讨论】:

  • sleep 1 是错误的代码。那是脆弱的。永远不要使用与时间相关的代码来控制多个线程。
  • @sawa 它只用于给时间线程完成,一般我使用 thread.join

标签: ruby multithreading mutex condition-variable


【解决方案1】:
  1. 您需要在互斥锁的同步块内工作 (mutex.synchronize do ... end)
  2. 如果第一个线程先运行,它可能会在其他线程 wait 之前完成,因此它们不会收到信号。
  3. signal 唤醒一个线程,因此其他线程也应该在完成唤醒下一个线程时发出信号

所以,试着把你的代码改成这样:

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

【讨论】:

  • 我试过使用 mutex.synchronize,结果变了。但是您的代码有时会从一个线程返回输出,有时输出来自所有线程。通常输出是不可预测的
  • 问题是, cv.wait 不会让线程等待信号。我不明白为什么
  • 您关于互斥同步的解释是正确的,但是您的代码并不能像您写的那样工作。 cv.signal 仍然可以在 cv.wait(mutex) 之前执行。
【解决方案2】:

经过一段时间的挣扎,我明白了问题所在。这都是关于条件变量的锁定。如果我的代码正确,我不知道,但它显示按顺序运行。

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

【讨论】:

    猜你喜欢
    • 2021-05-30
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多