Может ли рекурсивная функция выпустить свой собственный Mutex? - PullRequest
0 голосов
/ 16 апреля 2011

У меня есть некоторый код, метод класса для класса Ruby FootballSeries.find(123), который выполняет вызов API… из-за опасений по поводу безопасности потока, только один поток может войти в этот метод одновременно.В связи с некоторыми недавними изменениями в API, я также поддержал следующее… FootballSeries.find('Premiership'), второй вариант (см. Реализацию ниже) просто выполняет промежуточный вызов, чтобы проверить, можно ли найти идентификатор, а затем рекурсивно вызывает себя с использованием идентификатора..

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 (которая имеет достаточно смысла… поэтому мой вопрос, могу ли я разблокировать и повторно заблокировать мьютекс. (Я повторно блокирую, так чточто при выходе synchronize я не получу сообщение об ошибке разблокировки мьютекса, который мне не принадлежит… но я не проверял, требуется ли это)

Это нормальная реализация,или лучше бы мне, если бы find() вызывал два отдельных метода, каждый из которых был защищен своим собственным мьютексом? (пример find_by_id и find_by_name)

То, что у меня сейчас работает (или нанаименьшее количество работает).

Наконец, бонусные баллы за - как бы я протестировал такой метод на безопасность?

1 Ответ

0 голосов
/ 17 апреля 2011

Это не выглядит хорошо для меня, так как @find_mutex.unlock позволит одновременно вводить другие методы. Кроме того, я не думаю, что использование рекурсии является обычным явлением для такого рода отправки методов - на самом деле у вас есть два метода, встроенных в один. Я бы определенно разделил эти два, и если вы хотите иметь возможность вызывать один метод с разными типами аргументов, просто проверьте тип аргумента и вызовите один или другой. Если вам не нужно выставлять find_by_id и find_by_name, вы можете сделать их приватными и поместить mutex.synchronize только в find.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...