作者热门文章
- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
在我看来,用 Ruby MRI 1.8.7 编写文件是完全线程安全的。
示例 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 - 完美的结果(但速度较慢):
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 }
所以,我无法重建我面临并发问题的场景,你可以吗?
如果有人能向我解释为什么我仍然应该在这里使用 Mutex,我将不胜感激。
编辑:这是另一个更复杂的例子,它工作得很好并且没有显示并发问题:
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 }
最佳答案
我也无法产生错误。
您可能在这里遇到了文件锁定。如果您希望多个线程写入同一个文件,它们应该都使用相同的文件对象,如下所示:
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 引擎也是如此。
关于您应该在何处用锁保护您的代码的问题归结为,如果您想依赖您正在使用的 Ruby 引擎应该拯救您,或者您想要编写一个“应该”适用于所有系统的解决方案Ruby 引擎,不管它们是否有内置功能来避免并发问题。
另一个问题是,您的操作系统和/或文件系统是否正在使用文件锁将您从线程错误中拯救出来,以及您的代码是否应该独立于操作系统和/或文件系统,这意味着您不会依赖在文件系统锁上,以确保您的文件打开和写入由操作系统和/或文件系统正确同步。
我会大胆地说,这似乎是个好习惯,你也可以在你这边实现锁,以确保你的代码保持工作,无论是哪个 Ruby 引擎、操作系统或文件系统即使大多数现代 Ruby 引擎、操作系统和文件系统都内置了这些功能,其他人也会使用您的代码。
关于Ruby MRI 1.8.7 - 文件写入线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15108424/
我是一名优秀的程序员,十分优秀!