1つのプロセスに子スレッドと子プロセスがある場合、子プロセスは親プロセスのすべての子スレッドを継承しますか?
OSがLinuxであると想定します。 Javaスレッドモデルとする。
簡単に言えば、子プロセスは親から1つのスレッド、つまりfork
を呼び出していたスレッドを継承するということです。
これは、Posix/Pthreadsの観点からです。 Linuxは通常、Posixの近くにとどまろうとするため、これはほとんどLinuxにも当てはまりますが、LinuxはPosixの外部に動作が異なるいくつかの機能を備えている場合があります。
なぜすべてではなく1つのスレッドだけが継承されるのかと尋ねる人もいるかもしれません。どうやら、Posixの代替呼び出しforkall
は 検討および拒否 でした。一見すると、これは便利なようです。しかし、実際には、それがいかに扱いにくいバグにつながるかは簡単にわかります。スレッドAがファイルを開いており、ファイルに書き込みを発行しようとしている場合を考えます。その正確な瞬間に、スレッドBはforkall
を呼び出します。スレッドAは子プロセスで複製され、(一般に)開いているすべてのファイルが子プロセスで複製されるため、スレッドAとそのクローンは子both開いているファイルに書き込みます。これはおそらくエラーです。
子プロセスが単一のスレッドだけを継承するようにしても問題があります。 このstackoverflowの質問 と、それがリンクしている優れた ブログ記事 を参照してください。結局のところ、問題はありますが、対処することができます。
Pthreadに先行する Solaris Threads モデルは、フォークとスレッドに関して異なるポリシーを持っていました。デフォルトでは、fork
システムコールはallスレッドのクローンを作成しましたが、_fork1
_システムコールは呼び出しスレッドのみをクローンしました。さらに悪いことに、PthreadsがSolarisに実装されたとき、プログラムがリンクされた方法は、それがSolarisスレッドまたはPthreadsセマンティクスを使用しているかどうかを定義し、fork
のセマンティクスを決定しました。とても紛らわしい。
最後に、Javaスレッドについて質問しました。新しいプロセスがJavaでフォークされる方法は、Java.lang.Runtime.exec()
メソッドを使用することです。これは、Posix fork
とexec
の機能を融合したものです。一般に、サブプロセスはJava仮想マシン(JVM)を実行している必要はないため、親からのJavaスレッドはいずれも子に存在しません。子が最終的にJVMを実行する場合でも、そのJVMはstart-classのmain()
メソッドを実行することによって新しく開始し、親からスレッドを継承しません。