可以使用递归函数释放自己的互斥锁吗?

时间:2011-04-16 10:01:21

标签: ruby multithreading

我有一些代码,Ruby类FootballSeries.find(123)上的类方法,它执行API调用...由于担心线程安全,一次只有一个线程可以进入此方法。由于最近对API的一些更改,我也支持以下... FootballSeries.find('Premiership'),第二种(见下面的实现)只是进行临时调用,看看是否可以找到ID,然后使用递归调用自身ID。

class FootballSeries  
  @find_mutes = Mutex.new
  class << self
    def find(series_name_or_id)
      @find_mutex.synchronize do
        if series_name_or_id.is_a?(String)
          if doc = search_xml_document(series_name_or_id)
            if doc.xpath('//SeriesName').try(:first).try(:content) == series_name_or_id
              @find_mutex.unlock
              series = find(doc.xpath('//seriesid').first.content.to_i)
              @find_mutex.lock
              return series
            end
          end
        elsif series_name_or_id.is_a?(Integer)
          if doc = xml_document(series_name_or_id)
            Series.new(doc)
          end
        end
      end
    end
  end
end

没有第9行和第11行,就会出现recursive mutex lock: deadlock错误(这很有意义......因此我的问题是,我可以释放并重新锁定互斥锁。(我重新锁定,以便{{1}退出,我不会在解锁我不拥有的互斥锁时出错...但我没有测试是否需要这样做)

这是一个理智的实现,还是我会更好地让synchronize调用两个单独的方法,每个方法都使用自己的互斥锁进行保护? (示例find()find_by_id

我现在的工作(或者至少看起来有效)。

最后,奖励积分 - 我如何测试这种安全方法?

1 个答案:

答案 0 :(得分:0)

这对我来说不太好,因为@find_mutex.unlock将允许其他方法同时进入。此外,我不认为使用递归通常是这种方法调度 - 实际上你有两个方法塞进一个。我肯定将这两个分开,如果你想能够用不同的参数类型调用一个方法,只需检查参数的类型并调用其中一个。如果您不需要公开find_by_idfind_by_name,则可以将其设为私有,并将mutex.synchronize仅放在find中。