Railsガイドにマルチスレッドの扱い方に関して記述がある。

Rails のスレッドとコード実行 - Railsガイド

各スレッドは、アプリケーションのコードを実行する前にこのようにラップされるべきです。これにより、アプリケーションで何らかの作業を他のスレッドに手動で委譲する場合(Thread.newを使うなど)や、Concurrent Rubyのスレッドプールを用いる場合は、そのブロックをただちに以下のようにラップすべきです。

Thread.new do
  Rails.application.executor.wrap do
    # ここにコードを書く
  end
end

デフォルトのRailsアプリケーションでは、Executorのコールバックを以下の用途に用います。

  • 自動読み込みや再読み込みを安全に行えるスレッドがどれかをトラッキングする
  • Active Recordクエリキャッシュをオン/オフする
  • 獲得したActive Recordコネクションをコネクションプールに返す
  • 内部キャッシュの寿命を制限する

外側のスレッドは permit_concurrent_loads メソッドを呼び出すことでこのデッドロックを防げます。このメソッドを呼ぶと、提供されたブロック内で自動読み込みされた可能性のある定数をそのスレッドが参照解決しないことが保証されます。この保証に合致する最も安全な手法は、このメソッド呼び出しを、可能な限りブロッキングされる呼び出しの近くに配置することです。

Rails.application.executor.wrap do
  th = Thread.new do
    Rails.application.executor.wrap do
      User # 内側のスレッドは'load'ロックを取得し
           # Userを読み込んで続行できる
    end
  end

  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
    th.join # 外側のスレッドはここで待機するがロックを保持しない
  end
end

参考