Is Ruby's stdlib Logger class thread-safe?
A quick look at logger.rb reveals code such as the following:
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
So while I can't vouch for whether it gets thread-safety correct, I can confirm that it is making a concerted effort to do it right!
P.S. It's often easy to answer questions like this for yourself by reading the code :-)
Can Ruby's stdlib Logger class safely handle writers from multiple processes?
Yes, you can safely write interleaved log data to a single logfile in the way you've described.
However, you're better off logging a separate log for each process or using a consolidated logging system like syslog. Here's a couple of reasons why:
- Log Rotation/Management: truncating/rolling logfiles is difficult when you have to coordinate signalling multiple processes
- Interleaved data can be confusing even if you're injecting the PID to disambiguate
I'm currently managing a number of Resque workers per system with a single logfile and wish I had separated a logfile for each worker. It's been difficult debugging issues and managing the logs properly.
C++ Thread-Safe Map
Does not meet the criteria that you have specified, but you could have a look at the TBB containers. There is so called concurrent_hash_map
which allows multiple threads to access concurrently the data in the map. There are some details, but everything is nicely documented and can give you an idea of the "concurrent container". Depending on your needs this might be totally inappropriate...
What happens when you don't join your Threads?
After writing the question out, I realized that this is the exact thing that a web server does when serving pages. I googled and found the following article of a Ruby web server. The loop code looks pretty much like mine:
loop do
session = server.accept
request = session.gets
# log stuff
Thread.start(session, request) do |session, request|
HttpServer.new(session, request, basePath).serve()
end
end
Thread.start
is effectively the same as Thread.new
, so it appears that letting the threads finish and die off is OK to do.
How to increment (add value to) decimal in a thread-safe way?
Using lock is not overkill. It is required.
Structure types like System.Decimal are never atomic, it also doesn't fit the native cpu word size. Which is why Interlocked doesn't have an overload for it either.
Related Topics
Generate Array of Numbers That Fit to a Probability Distribution in Ruby
Find Products Matching All Categories (Rails 3.1)
How to Remove the Zone from a Datetime Value
Another Way Instead of Escaping Regex Patterns
How to Populate an Array with Random Numbers
Ruby on Rails Activerecord Scopes VS Class Methods
Rails 4: How to Upload Files with Ajax
How to Force Rails to Load All Models
Devise Not Displaying Error Messge During an Authentication Failure
Positive Lookahead Doesn't Stop at First Occurrence
(New to Rails) Rails Server Error: Cannot Load Such File -- Bootsnap/Setup (Loaderror)
Getting Current Line of Code in Ruby
Automatic Associations in Ruby on Rails Fixtures
How to Run "Bundle Exec Jekyll New ."