Недавно я реализовал приложение Rails, использующее потоки, и сделал несколько открытий:
Во-первых, если вы пишете в какие-либо массивы или хэши (например, сложные типы) вне вашего потока, заключите их в мьютекс. Мне кажется, что ссылки на хэш и массивы не могут быть потокобезопасными. Кажется маловероятным, что индексация элементов хэша / массива не является потокобезопасной, но все, что я знаю, это то, что после того, как я поместил внешние структуры данных в мьютекс перед записью, проблемы исчезли.
Во-вторых, закройте соединение ActiveRecord, когда поток завершится, иначе вы можете создать большое количество устаревших соединений. Вот сообщение о том, как это сделать. >. Я не знаю, применимо ли это по-прежнему к версиям Rails> 2.2, но после того, как я начал явно закрывать соединения, мои проблемы исчезли. Автор предлагает исправить ActiveRecord, чтобы сделать это автоматически, но я решил явно освободить соединения в своем коде.
Вот пример кода, который у меня работает:
mutex = Mutex.new
my_array = []
threads = []
1.upto(10) do |i|
threads << Thread.new {
begin
do_some_stuff
mutex.synchronize {
# You'd think that each thread would only touch its own personal
# array element but without a mutex, I run into problems.
my_array[i] = some_computed_value
}
ensure
ActiveRecord::Base.connection_pool.release_connection
end
}
}
threads.each {|t| t.join}
Кстати, если вы используете потоки для использования преимуществ многоядерных процессоров, вам необходимо использовать JRuby. Насколько мне известно, JRuby - единственная реализация, которая может использовать собственные потоки ЦП. Если вы используете потоки, чтобы делать другие вещи во время ожидания сетевых подключений или некоторых других задач, не связанных с процессором, это не проблема.
person
Mark Westling
schedule
04.11.2009