Rails中的多线程并发和加载错误

时间:2012-02-14 01:12:10

标签: ruby-on-rails multithreading

我写了一个简单的应用程序来测试多个线程在Rails中对模型/数据库的并发访问。

我创建了一个模型Counter,它有一个整数属性“count”。

然后我有一个脚本创建3个线程,它们同时读取数据库中第一个count的{​​{1}}的当前值,即11。这是代码:

Counter

我总是在 1 def func(index) 2 puts "[thr#{index}] this is #{Thread.current}" 3 i = 0; 4 while i < 5 5 puts "[thr#{index}] #{Time.now} #{index}.#{i} read count = #{Counter.first.count}" 6 i += 1 7 sleep(1) 8 end 9 end 10 11 ###loc_A### 12 puts "[main] started At #{Time.now}" 13 14 all_threads = [] 15 1.upto(3) do |index| 16 all_threads << Thread.new{func(index)} 17 ###loc_B### 18 end 19 all_threads.each { |t| t.join } 20 21 puts "[main] end at #{Time.now}" 中收到LoadError个例外:

active_support/dependencies.rb

Thread1运行完成,但似乎第二个线程[thr2]在访问模型Counter时退出LoadError并退出,第三个线程可能也是如此。

现在,如果我通过添加此行来访问线程之前的模型

04:32 PM ~/app/test_multithread $ rails runner script/multithread.rb 
[main] started At 2012-02-13 16:33:03 -0800
[thr1] this is #<Thread:0x00000100e1b288>
[thr2] this is #<Thread:0x00000100e1b0a8>[thr3] this is #<Thread:0x00000100e1aef0>

[thr1] 2012-02-13 16:33:03 -0800 1.0 read count = 11
[thr1] 2012-02-13 16:33:05 -0800 1.1 read count = 11
[thr1] 2012-02-13 16:33:06 -0800 1.2 read count = 11
[thr1] 2012-02-13 16:33:07 -0800 1.3 read count = 11
[thr1] 2012-02-13 16:33:08 -0800 1.4 read count = 11
/Users/whk/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:490:in `load_missing_constant': Expected /Users/whk/Development/rails_projects/test_multithread/app/models/counter.rb to define Counter (LoadError)
    from /Users/whk/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:181:in `block in const_missing'
    from /Users/whk/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:179:in `each'
    from /Users/whk/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:179:in `const_missing'
    from script/multithread.rb:5:in `func'
    from script/multithread.rb:16:in `block (2 levels) in <top (required)>'

puts "[main] #{Counter.inspect.to_s}" ,然后所有三个线程都成功运行完成。

#loc_A

或者,如果我通过添加此行在每个线程的创建之间插入延迟

04:36 PM ~/app/test_multithread $ rails runner script/multithread.rb 
[main] Counter(id: integer, count: integer, ts: datetime, created_at: datetime, updated_at: datetime)
[main] started At 2012-02-13 16:36:57 -0800
[thr1] this is #<Thread:0x000001016410e8>
[thr2] this is #<Thread:0x00000101640f08>[thr3] this is #<Thread:0x00000101640e40>
[thr1] 2012-02-13 16:36:57 -0800 1.0 read count = 11

[thr2] 2012-02-13 16:36:57 -0800 2.0 read count = 11
[thr3] 2012-02-13 16:36:57 -0800 3.0 read count = 11
[thr1] 2012-02-13 16:36:58 -0800 1.1 read count = 11
[thr2] 2012-02-13 16:36:58 -0800 2.1 read count = 11
[thr3] 2012-02-13 16:36:58 -0800 3.1 read count = 11
[thr1] 2012-02-13 16:36:59 -0800 1.2 read count = 11
[thr2] 2012-02-13 16:36:59 -0800 2.2 read count = 11
[thr3] 2012-02-13 16:36:59 -0800 3.2 read count = 11
[thr1] 2012-02-13 16:37:00 -0800 1.3 read count = 11
[thr2] 2012-02-13 16:37:00 -0800 2.3 read count = 11
[thr3] 2012-02-13 16:37:00 -0800 3.3 read count = 11
[thr1] 2012-02-13 16:37:01 -0800 1.4 read count = 11
[thr2] 2012-02-13 16:37:01 -0800 2.4 read count = 11
[thr3] 2012-02-13 16:37:01 -0800 3.4 read count = 11
[main] end at 2012-02-13 16:37:02 -0800

sleep(1) ,所有三个线程也都运行完毕。

问题似乎与模型的加载有关。如果预先模拟了模型,或者给定了加载时间,则不会发生LoadError。模型是否为所有线程加载一次,为每个线程单独加载?任何人都可以向我解释这个吗?

我的环境是

  • sqlite3
  • Rails 3.1.1
  • ruby​​ 1.9.2p290

1 个答案:

答案 0 :(得分:0)

这是由于ruby中的自动加载问题。自动加载不是线程安全的。您可以通过添加 require 语句来解决此问题。

我在Rails应用程序中遇到了类似的问题。而且我通过急于加载线程所需的模块来解决该问题。