Ruby MRI 1.8.7-文件写入线程安全 [英] Ruby MRI 1.8.7 - File writing thread safety

查看:80
本文介绍了Ruby MRI 1.8.7-文件写入线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我看来,用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆