0

私はスレッドについて学び始めました、そして今、本が私をユーザーレベルとカーネルレベルのスレッドと混同するところまで来ています。

この本は違いを強調し、問題を提示しています。次の2つの類似したコードの出力は異なりますが、(私の知る限り)それらの出力は私には同じように見えます。

1つ目は、ユーザーレベルのスレッドに関するものです。

int number = 0;
int main() {
fork()
if it is child {number--, return 0}
if it is parent {number++, wait till child return, print number}}

私の分析では、number--とnumber ++は1回だけ実行する必要があり、これら2回の実行後に出力が出力されるため、出力は0でなければなりません。

2番目のケースは、カーネルレベルのスレッドに関するものです。

int number = 0;
t1() {number--}
t2() {number++}
main() {
    createThread(pass t1)
    createThread(pass t2)
    wait till both complete
    print number
}

この場合、同じことですが、カーネルは2つのスレッドを作成します。1つは-、もう1つは++であるため、両方を1回だけ実行する必要があります。結果は再び0でなければなりません。

しかし、本は出力が異なる、または介入のために異なる出力があるかもしれないと言っています、誰かが理由を教えてもらえますか?

4

3 に答える 3

2

最初のケースでは、スレッドを作成するのではなく、プロセスを fork します (fork() 関数の説明を参照してください)。フォークされたプロセスには、親プロセスからコピーされた独自のメモリがあるため、子プロセスの数を減らした結果は、親プロセスには影響しません。親プロセスで number を出力した結果は 1 になります。

于 2012-09-13T05:17:44.030 に答える
1

単一の命令を書いたとしても、機械語で複数の命令に翻訳される場合もありますi++i--カーネル スレッドを使用している場合、これら 2 つの計算は異なるコアで実行され、それぞれが の「その」値をキャッシュしますi。この場合、実際にメモリに書き込まれる結果は未定義です。これは、ハードウェアとコンパイラが背後で誰もデータを変更していないと想定しているためです。

于 2012-09-13T02:05:39.213 に答える
0

スレッド化されたケースでは、データの競合が発生する可能性があるため、最終値を取得すること1も可能です。-1スレッド 1 が終了した後にスレッド 2 が開始される、またはその逆になるという保証はないため、適切な同期がなければ、両方のスレッドがほぼ同時に開始され、 の初期値が表示される可能性があり0ます。次に、どのスレッドが 2 番目に終了するかに応じて、値は の代わりに1またはになります。これを回避するには、クリティカル セクションやアトミック イン/デクリメントなどの同期イディオムを使用する必要があります。-10

于 2012-09-13T10:10:27.940 に答える