gpt4 book ai didi

ruby - 如何使用条件变量?

转载 作者:数据小太阳 更新时间:2023-10-29 07:34:29 26 4
gpt4 key购买 nike

关于 Ruby 中的条件变量的资源不多,但其中大部分都是错误的。喜欢ruby-doc , tutorial herepost here - 他们都可能陷入僵局。

我们可以通过按给定顺序启动线程并可能在两者之间放置一些 sleep 来强制同步来解决这个问题。但这只是推迟了真正的问题。

我将代码重写成经典的producer-consumer problem :

require 'thread'
queue = []
mutex = Mutex.new
resource = ConditionVariable.new
threads = []

threads << Thread.new do
5.times do |i|
mutex.synchronize do
resource.wait(mutex)
value = queue.pop
print "consumed #{value}\n"
end
end
end

threads << Thread.new do
5.times do |i|
mutex.synchronize do
queue << i
print "#{i} produced\n"
resource.signal
end
sleep(1) #simulate expense
end
end

threads.each(&:join)

有时你会得到这个(但不总是):

0 produced
1 produced
consumed 0
2 produced
consumed 1
3 produced
consumed 2
4 produced
consumed 3
producer-consumer.rb:30:in `join': deadlock detected (fatal)
from producer-consumer.rb:30:in `each'
from producer-consumer.rb:30:in `<main>'

什么是正确的解决方案?

最佳答案

问题是,正如您之前评论的那样,这种方法只有在您可以保证使用者线程在我们的程序开始时首先获取互斥体时才有效。如果不是这种情况,则会发生死锁,因为生产者线程的第一个 resource.signal 将在消费者线程尚未等待资源时发送。结果,第一个 resource.signal 基本上不会做任何事情,所以你最终会遇到调用 resource.signal 4 次的场景(因为第一个丢失了),而 resource.wait 被调用了 5 次。这意味着消费者将永远等待,并发生死锁。

幸运的是,我们可以通过只允许消费者线程在没有更多即时工作可用时开始等待来解决这个问题。

require 'thread'
queue = []
mutex = Mutex.new
resource = ConditionVariable.new
threads = []

threads << Thread.new do
5.times do |i|
mutex.synchronize do
if queue.empty?
resource.wait(mutex)
end
value = queue.pop
print "consumed #{value}\n"
end
end
end

threads << Thread.new do
5.times do |i|
mutex.synchronize do
queue << i
print "#{i} produced\n"
resource.signal
end
sleep(1) #simulate expense
end
end

threads.each(&:join)

关于ruby - 如何使用条件变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13086107/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com