Является ли класс Ruby stdlib Logger потокобезопасным?

Короче говоря, является ли класс стандартной библиотеки Logger в Ruby потокобезопасным? Единственная полезная информация, которую нашел Google, была тем, что кто-то на форуме сказал, что это «кажется» потокобезопасным. И мне не хочется тратить время на тестирование логгера, чтобы выяснить, так это или нет.

В настоящее время я использую log4r, который является потокобезопасным, но это излишне, если стандартная библиотека уже делает это. Это.


person jimeh    schedule 11.01.2011    source источник


Ответы (4)


Беглый взгляд на logger.rb показывает следующий код:

def write(message)
  @mutex.synchronize do
    if @shift_age and @dev.respond_to?(:stat)
      begin
        check_shift_log
      rescue
        raise Logger::ShiftingError.new("Shifting failed. #{$!}")
      end
    end
    @dev.write(message)
  end
end

Так что, хотя я не могу поручиться за правильный потокобезопасность, я могу подтвердить, что он прилагает согласованные усилия, чтобы сделать это правильно!

P.S. Часто легко ответить на подобные вопросы самостоятельно, прочитав код :-)

person Avdi    schedule 11.01.2011

Ниже приведен мой первоначальный ответ, который на самом деле неправильный. Прочитайте комментарий Nemo157 ниже. Я оставил его здесь только для справки.

Оригинал:

Я не думаю, что это имеет значение. Все реализации Ruby, которые я знаю до сих пор, в любом случае эффективно запускают один поток за раз: он позволяет вам запускать много потоков, но только один поток запускается в каждый момент времени для каждого процесса.

person kirakun    schedule 11.01.2011
comment
Да, но даже если одновременно выполняется только один поток, это не делает многопоточный код Ruby потокобезопасным, поскольку то, что должно быть атомарными операциями, может охватывать несколько операторов. Например. x = point.x; point.x = x + 1 поток может быть прерван между двумя операторами, а другой поток может изменить значение point.x, которое будет перезаписано при возобновлении этого потока. Кроме того, JRuby действительно многопоточен, поскольку использует потоки Java. - person Nemo157; 12.01.2011

Некоторые классы Ruby спроектированы так, чтобы быть потокобезопасными, но в их документации об этом явно не говорится односложными словами. В отличие от документации на других языках программирования, таких как PHP.

Я помню, как меня спросили, является ли Queue потокобезопасным при переполнении стека, и хотя это было так, в документации это не разъяснялось.

person Andrew Grimm    schedule 11.01.2011

источник

Попробуйте, если журналы будут смесью в многопоточности

require 'logger'
require 'parallel'

logger = Logger.new("/tmp/test.log")

Parallel.map(['a','b'], :in_threads => 2) do |letter|
  1000.times do
    logger.info letter * 5000
  end
end

Проверка файла журнала

egrep -e 'ab' -e 'ba' /tmp/test.log
[empty]

Причина, по которой логи не смешались:

def write(message)
  @mutex.synchronize do
    ...    
    @dev.write(message)        
  end
end
person Sarah Mostafa    schedule 06.10.2020