メモ
fork(2) システムコールを使ってプロセスの複製を作ります
ブロックを指定して呼び出した場合には、生成した子プロセスでブロックを評価します。
https://docs.ruby-lang.org/ja/latest/method/Kernel/m/fork.html
fork.rb
i = 10
puts "object_id: #{i.object_id}" #=> 21
3.times do
fork do
puts "object_id: #{i.object_id}" #=> 21 (ObjectIDは親プロセスの時の値と変わらない)
i += 1
puts i # => 常に11(元々の親プロセスの10が引き継がれる)
end
end
Process.waitall # すべての子プロセス終了まで待つ
puts "end: #{i}" # => end: 10 (子プロセスのインクリメントは影響されない)
実行結果
% ruby fork.rb
object_id: 21
object_id: 21
11
object_id: 21
11
object_id: 21
11
end: 10
Thread オブジェクトの場合
Threadオブジェクトも複製されて Thread.current
や object_id は親プロセスと子プロセスとで同じものが参照されるが、OSレベルでスレッドIDを確認するとちゃんと別々のが確認できる。
参考: 【Ruby】スレッドID(tid)を表示する
puts Thread.current # => #<Thread:0x0000565035403310 run>
puts syscall(186) #=> 24837
fork do
puts Thread.current # => #<Thread:0x0000565035403310 run>
puts syscall(186) # => 24891
end
ちなみにThread.currentで子プロセスで値を代入しても、もちろん親では参照できない。
Thread.current[:hoge] = "hoge"
fork do
puts Thread.current[:hoge] # => hoge (親のが複製)
Thread.current[:hoge] = "hoge2"
end
Process.waitall
puts Thread.current[:hoge] # => hoge (子の影響は受けない)
参考
なるほどUnixプロセス ― Rubyで学ぶUnixの基礎 - 達人出版会
https://tatsu-zine.com/books/naruhounix