Ruby 的线程速度

标签 ruby multithreading file-io thread-safety

我有以下代码可以线程安全地写入文件:

threads = []
@@lock_flag = 0
@@write_flag = 0

def add_to_file
    old_i = 0
    File.open( "numbers.txt", "r" ) { |f| old_i = f.read.to_i }
    File.open( "numbers.txt", "w+") { |f| f.write(old_i+1) }
    #puts old_i
end

File.open( "numbers.txt", "w") { |f| f.write(0) } unless File.exist? ("numbers.txt")

2000.times do
    threads << Thread.new {
        done_flag = 0
        while done_flag == 0 do
            print "."           #### THIS LINE
            if @@lock_flag == 0
                @@lock_flag = 1
                if @@write_flag == 0
                    @@write_flag = 1
                    add_to_file
                    @@write_flag = 0
                    done_flag = 1
                end
                @@lock_flag = 0
            end
        end
    }
end

threads.each {|t| t.join}

如果我运行这段代码,将所有 2000 个数字写入文件大约需要 1.5 秒。所以,一切都很好。 但是,如果我删除标有“THIS LINE”的 print ". 行需要很长时间!此代码仅需 20 个线程即可完成大约 12 秒。

现在我的问题是:为什么 print 会大大加快该代码的速度?

最佳答案

我不确定当它根本不安全时,您怎么能称该线程安全。由于竞争条件,您不能使用简单的变量来确保安全。在测试标志为零和将其设置为 1 之间会发生什么?你根本不知道。如果您足够不幸,任何事情都可能并且最终会在那非常短暂的时间间隔内发生。

可能发生的情况是 print 语句导致线程停顿足够长的时间,以至于您损坏的锁定机制最终起作用。当使用 Ruby 1.9.2 测试该示例时,它甚至没有完成,似乎永远打印点。

您可能想尝试使用 Mutex 重写它:

write_mutex = Mutex.new
read_mutex = Mutex.new

2000.times do
    threads << Thread.new {
        done_flag = false
        while (!done_flag) do
            print "."           #### THIS LINE
            write_mutex.synchronize do
              read_mutex.synchronize do
                add_to_file
                done_flag = true
              end
            end
        end
    }
end

这是进行线程同步的正确 Ruby 方法。在确定您对它具有独占控制权之前,Mutex 不会放弃锁。还有 try_lock 方法会尝试获取它,如果它已经被获取,则会失败。

线程可能真的很麻烦,所以在使用它们时要非常小心。

关于Ruby 的线程速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7027103/

相关文章:

ruby - Ruby 程序的结构

ios - 每次滚动后 tableview 中的图像都会发生变化

c# - 如何使用 System.IO.Directory.GetFiles 递归枚举文件+文件夹

java - 读取文件并将数据从文件发送到 JTable

ruby-on-rails - 找不到回形针文件错误

ruby-on-rails - 找不到 libcurl 或 curl/curl.h (RuntimeError)

ruby-on-rails - authlogic - session 创建失败的原因并且没有错误消息(使用 formtastic)

c# - 线程测试题

java - 在java中,如何让单个线程等待进程完成?

c++ - c++ fstream 的文件读/写有 2G 限制吗?