Ruby MRI 1.8.7 – 文件编写线程安全性
在我看来,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}contentn" 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}contentn" } 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 } 解决方法
我也无法产生错误.
你可能在这里遇到了文件锁.如果您希望多个线程写入同一个文件,它们应该使用相同的文件对象,如下所示: 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 end end threads.each{ |thread| thread.join } 在这个例子中,GIL可能会让你免于任何真正的线程错误,但我不确定,在JRuby下会发生什么,它使用真正的线程并且两次写入可能在同一时间发生.其他具有真实线程的Ruby引擎也是如此. 关于你应该用锁来保护你的代码的问题归结为,如果你想依赖你正在使用的Ruby引擎应该保存你,或者你想编写一个“应该”适用于所有Ruby引擎的解决方案,无论它们是否具有内置功能,都可以避免并发问题. 另一个问题是,如果您的操作系统和/或文件系统正在使用文件锁保存您的线程错误,并且您的代码应该是操作系统和/或文件系统独立的,这意味着您不会依赖于文件 – 系统锁定以确保操作系统和/或文件系统正确地同步文件打开和写入. 我会说,看起来这是一个好习惯,你也可以在你身边实现锁定,以确保你的代码能够继续工作,无论其他人是Ruby引擎,操作系统还是文件系统即使大多数现代Ruby引擎,操作系统和文件系统都内置了这些功能,也会使用您的代码. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |