Ruby MRI 1.8.7-文件写入线程安全 [英] Ruby MRI 1.8.7 - File writing thread safety
问题描述
在我看来,用Ruby MRI 1.8.7编写文件是完全线程安全的.
It seems to me that file writing in Ruby MRI 1.8.7 is completely thread safe.
示例1-完美的结果:
File.open("test.txt", "a") { |f|
threads = []
1_000_000.times do |n|
threads << Thread.new do
f << "#{n}content\n"
end
end
threads.each { |t| t.join }
}
示例2-完美的结果(但速度较慢):
Example 2 - Flawless Results (but slower):
threads = []
100_000.times do |n|
threads << Thread.new do
File.open("test2.txt", "a") { |f|
f << "#{n}content\n"
}
end
end
threads.each { |t| t.join }
所以,我无法重建遇到并发问题的情况,可以吗?
So, I couldn't reconstruct a scenario where I face concurrency problems, can you?
如果有人能向我解释为什么我仍然应该在这里使用Mutex,我将不胜感激.
I would appreciate if somebody could explain to me why I should still use Mutex here.
这是另一个更复杂的示例,可以很好地工作并且不会显示并发问题:
here is another more complicated example which works perfectly fine and doesn't show concurrency problems:
def complicated(n)
n.to_s(36).to_a.pack("m").strip * 100
end
items = (1..100_000).to_a
threads = []
10_000.times do |thread|
threads << Thread.new do
while item = items.pop
sleep(rand(100) / 1000.0)
File.open("test3.txt", "a") { |f|
f << "#{item} --- #{complicated(item)}\n"
}
end
end
end
threads.each { |t| t.join }
推荐答案
我也无法产生错误.
您可能在这里遇到了文件锁.如果希望多个线程写入同一文件,则它们都应使用相同的文件对象,如下所示:
You are probably running into a file lock here. If you wish for multiple threads to write to the same file, they should all use the same file-object like so:
File.open("test.txt", "a") do |fp|
threads = []
500.times do |time|
threads << Thread.new do
fp.puts("#{time}: 1")
sleep(rand(100) / 100.0)
fp.puts("#{time}: 2")
end
end
threads.each(&:join)
end
在此示例中,GIL可能会使您免于任何实际的线程错误,但我不确定,在使用实际线程的JRuby下会发生什么,并且可能在同一时间发生两次写入.其他具有真正线程化功能的Ruby引擎也是如此.
The GIL will probably save you from any real thread-bugs in this example, but I am not really sure, what would happen under JRuby, which is using real threads and two writes might occur at the exact same time. The same goes for other Ruby-engines with real threadding.
关于应在何处使用锁保护代码的问题归结为,如果您要依赖所使用的Ruby引擎,则可以挽救您,或者您想编写一种应该"使用的解决方案.可以在所有Ruby引擎上运行,无论它们是否具有内置功能可以使您免于并发问题.
Regarding the question of wherever you should protect your code with locks comes down to, if you want to rely on the Ruby-engine you are using should save you, or you want to code a solution that "should" work on all Ruby-engines, regardless of if they have built-in functionality to save you from concurrency problems.
另一个问题是,您的操作系统和/或文件系统是否将您从具有文件锁的线程错误中拯救出来,并且您的代码是否应独立于操作系统和/或文件系统,这意味着您将不会依赖文件系统锁,以确保操作系统和/或文件系统已正确同步您的文件打开和写入.
Another question is if your operation-system and/or file-system is saving you from thread-bugs with file locks, and if your code should be operating-system and/or file-system independent, meaning that you wont depend on file-system locks to ensure, that your file-opening and writes are being properly synchronized by the operation-system and/or file-system.
我会弯腰说,这似乎是一种好习惯,您也应该在自己的一边实现锁,以确保无论使用哪种Ruby引擎,操作系统或文件系统,代码都可以正常工作即使大多数现代Ruby引擎,操作系统和文件系统都内置了这些功能,其他人也会在上面使用您的代码.
I will go out on a limb and say, that it seems like good practice, that you also implement locks on your side, to ensure that your code keeps working regardless of which Ruby-engine, operating-system or file-system someone else is going to use your code on, even though most modern Ruby-engines, operating-systems and file-systems have these features built-in.
这篇关于Ruby MRI 1.8.7-文件写入线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!