示例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" } endendthreads.each { |t| t.join }
所以,我无法重建我遇到并发问题的场景,对吗?
如果有人能向我解释为什么我仍然应该在这里使用Mutex,我将不胜感激.
编辑:这是另一个更复杂的例子,它完美地工作,并没有显示并发问题:
def complicated(n) n.to_s(36).to_a.pack("m").strip * 100enditems = (1..100_000).to_athreads = []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 endendthreads.each { |t| t.join }解决方法 我也无法产生错误.
你可能在这里遇到了文件锁.如果您希望多个线程写入同一个文件,它们应该使用相同的文件对象,如下所示:
threads = []file.open("test.txt","a") do |fp| 500.times do |time| threads << Thread.new do fp.puts("#{time}: 1") sleep(rand(100) / 100.0) fp.puts("#{time}: 2") end endendthreads.each{ |thread| thread.join }
在这个例子中,GIL可能会让你免于任何真正的线程错误,但我不确定,在JRuby下会发生什么,它使用真正的线程并且两次写入可能在同一时间发生.其他具有真实线程的Ruby引擎也是如此.
关于你应该用锁来保护你的代码的问题归结为,如果你想依赖你正在使用的Ruby引擎应该保存你,或者你想编写一个“应该”适用于所有Ruby引擎的解决方案,无论它们是否具有内置功能,都可以避免并发问题.
另一个问题是,如果您的 *** 作系统和/或文件系统正在使用文件锁保存您的线程错误,并且您的代码应该是 *** 作系统和/或文件系统独立的,这意味着您不会依赖于文件 – 系统锁定以确保 *** 作系统和/或文件系统正确地同步文件打开和写入.
我会说,看起来这是一个好习惯,你也可以在你身边实现锁定,以确保你的代码能够继续工作,无论其他人是Ruby引擎, *** 作系统还是文件系统即使大多数现代Ruby引擎, *** 作系统和文件系统都内置了这些功能,也会使用您的代码.
总结以上是内存溢出为你收集整理的Ruby MRI 1.8.7 – 文件编写线程安全性全部内容,希望文章能够帮你解决Ruby MRI 1.8.7 – 文件编写线程安全性所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)