Running rake middleware
on a basic rails app gives the following:
use Rack::Lock
use ActionController::Failsafe
use ActionController::Reloader
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActiveRecord::SessionStore, #<Proc:0x017fb394@(eval):8>
use ActionController::RewindableInput
use ActionController::ParamsParser
use Rack::MethodOverride
use Rack::Head
run ActionController::Dispatcher.new
The first item on the rack stack is Rack::Lock
. This puts a lock around each request, so only one request is handled at a time. As such a standard rails app is single threaded. You can however spawn new threads within a request that would make your app multi threaded, most people never encounter this.
If you are having issues…
require 'thread'
Thread.exclusive do
# stuff here
end
… would ensure that stuff inside the block is never run in parallel with any other code. Creating a shared Mutext
between all threads (in a class variable or something, but this could be wiped when reloaded in dev mode, so be careful), and locking on it as Rack::Lock#call
does is to be preferred if you just want to ensure no two instances of the same code is executed at the same time.
Also, for the record, each request creates and dereferences one controller in each request cycle. No two requests should see the same instance, although they may see the same class.
Setting config.threadsafe!
voids almost everything I said. That removes Rack::Lock
from the stack, and means you will need to set a mutex manually to prevent double entry. Don't do it unless you have a really good reason.
Even without Rack::Lock
you will still get one controller instance per request. The entry point to your controller ensures that, notice the call to new
in process
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…