ruby – 如何使用条件变量?
发布时间:2020-12-17 02:19:14 所属栏目:百科 来源:网络整理
导读:Ruby中的条件变量资源不多,但大多数都是错误的.像 ruby-doc,tutorial here或 post here一样 – 所有人都可能陷入僵局. 我们可以通过以给定顺序启动线程来解决问题,并且可能在两者之间进行一些睡眠以强制执行同步.但那只是推迟了真正的问题. 我将代码重写为经
Ruby中的条件变量资源不多,但大多数都是错误的.像
ruby-doc,tutorial here或
post here一样 – 所有人都可能陷入僵局.
我们可以通过以给定顺序启动线程来解决问题,并且可能在两者之间进行一些睡眠以强制执行同步.但那只是推迟了真正的问题. 我将代码重写为经典的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} producedn" 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} producedn" resource.signal end sleep(1) #simulate expense end end threads.each(&:join) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |