図で理解!!並列(Concurrency)並行(Parallelism)の違い
公開: 2025年12月02日
昨日、非同期処理(サイドキック)で処理することとなったパフォーマンス改善のタスクの設計していると、処理中のステータスどうする(enumの値を-1とかで用意?)?もし失敗したらどうする?トランザクションの外だよねぇ?論理削除する?じゃあカラムもいるなぁとか結構な課題が出て来ました。
自分なりに考えてこんな感じで実装していいっすか?とCTOと話していると、「これ並列処理でもよくない?どう思う?」ってなり、ほうほう、そんなこともできるのね!と思ったら、さらに「Threadでも良さそう!これ見て」とリンクが届き、claudeにも聞いてみると「Threadで十分!」って言われました。
CTO「これは並行処理で〜、、、hogehoge」
(え、並列じゃないん?並行って何??並列と違うん??)
実は並列と並行は似ているけど別物で、ここを理解しないと判断できない…!と思い、しっかり調べました。
Railsに限らない概念のお話です!!
物理的に同時に実行する
→ CPU内のコアを複数使って同時に実行する
同時にやっているように見える仕組み
→ 実際はタスクを高速で切り替えているだけで直列の処理
私は文章より「頭の中の図」で理解するタイプなので、今回も脳内イメージをそのまま図にしてみました!
今回は外部I/O(S3アップロードでしかもキャッシュのコピー)の処理待ちで時間がかかっていたので、一つ処理投げたら待ってる間に次の処理投げる、という感じで直列の処理でありつつ待機時間をただ待つだけにしないということを実現しました。
多忙な母親が、ただぼーっとしているだけの時間を過ごさずに炊飯器セットしてお風呂沸かして子供の宿題をゆっくり見ているような感じですね。
並列はベビーシッター召喚してるって感じでしょうか!
ここが今回一番ハマったポイントで、Rails寄りの話になりますが、
どの言語でも 並行処理 × トランザクションの組み合わせは基本うまくいかない ので、知っておくと役立ちそうです。
並行処理(Thread)は Rails のトランザクションを共有できません。
理由は以下の通りです(Rails版ですが)
ActiveRecord は スレッドごとに別の DB コネクション を取る
親スレッドで transaction do を開始してもThread 内では 別コネクションで処理されるため、BEGIN の外側になる
→つまり Thread で保存したレコードは、親スレッド側の rollback の影響を受けません。
結局は関連の処理終わったら並行処理開始して、そこで失敗したら論理削除するって実装にしました!!!!
CTOも確かにそもそもレイテンシーが上がる原因になっているような重い外部I/Oの処理をトランザクションの中でするべきではないって言ってました。
トランザクションの処理をしている間はDBにロックがかかっちゃうから長時間は避けたいということですね。
確かに確かに。
日々勉強です!!!!
やはりAIがあるので「猿でもわかるように」でだいぶ優しく教えてもらえるし、「わかんない」で諦めなければなんでもできるようになりそう!!って思います!!
折れない心が大事です!!!
