2021年2月22日月曜日、天気は良いです[過去を嘆いたり、現在を無駄にしたり、未来を恐れたりしないでください]
この記事の内容
1.オペレーティングシステムのアトミック操作
アトミック操作は分割できず、実行前に他のタスクやイベントによって中断されることはありません。
単一スレッドでは、単一の命令で完了できる操作はアトミック操作と見なすことができ、割り込みは命令間でのみ発生する可能性があるため、単一の命令で完了できない操作も非アトミック操作と見なすことができます。
マルチスレッドでは、他のプロセス(スレッド)によって中断できない操作はアトミック操作と呼ばれます。
2.アセンブリコードから、++ iとi ++がアトミック操作であるかどうかを確認します
++i;
00007FF7D69F17E8 mov eax,dword ptr [i]
00007FF7D69F17EB inc eax
00007FF7D69F17ED mov dword ptr [i],eax
i++;
00007FF7D69F17F0 mov eax,dword ptr [i]
00007FF7D69F17F3 inc eax
00007FF7D69F17F5 mov dword ptr [i],eax
++ iとi ++の両方が次の3つの命令を使用して実装されていることがわかります。
1.メモリからレジスタに値をコピーします;
2。レジスタの自動インクリメント;
3。レジスタからメモリに値をコピーします;
したがって、++ iとi ++はアトミック操作ではありません。
3.一般的な問題:プロセスにグローバル変数iと2つのスレッドがあります。i ++は2つのスレッドで100回実行されます。取得できる最大値と最小値は何ですか?
3.1マルチコアCPUの最小値は2、最大値は200です。
上記から、i ++は3つの命令で構成される算術演算であることがわかります。2つのスレッドは、i変数に対して合計100(サイクル)* 3(命令)* 2(スレッド)= 600の命令を実行する必要があります。特定の配置により、iの最終値は2になります。
2つのスレッドの実行ステップが次のとおりであり、iの最終値が2のみであるとします。
-
スレッドAは初めてi ++を実行し、メモリからiを取り出し、値を0にして、レジスタに格納した後に1を加算します。このとき、CPU1のレジスタの値は1で、メモリは0です。
-
スレッドBは初めてi ++を実行し、メモリからiをフェッチし、値を0にして、レジスタに格納した後に1を加算します。このとき、CPU2のレジスタの値は1で、メモリの値です。は0です。
-
スレッドAは引き続き99番目のi ++を実行し、値をメモリに戻します。このとき、CPU1のレジスタの値は99で、メモリの値は99です。
-
スレッドBは最初のi ++を実行し続け、その値をメモリに戻します。このとき、CPU2のレジスタ値は1で、メモリは1です。
-
スレッドAはi ++を100回実行し、メモリ内の値をCPU1のレジスタにフェッチして戻し、インクリメントを実行します。このとき、CPU1のレジスタ内の値は2で、メモリ内の値は1です。
-
スレッドBはすべての操作を実行し、それをメモリに戻します。このとき、CPU2のレジスタ値は100で、メモリは100です。
-
スレッドAは100回の操作の最後の部分を実行し、CPU1のレジスタ値をメモリに戻します。メモリの値は2です。
200の結果は比較的単純であり、間隔を置いて動作するために必要なスレッドは2つだけです。
3.2シングルコアCPUの最小値は100、最大値は200です。
2つのスレッドはスレッド1とスレッド2としてマークされています。i++は、iの値を取り出し、1を加算して、元に戻すのと同じです。
最初の極端なケース:スレッド1がiの値を取得するたびに、CPU時間はスレッド2に切り替わり、スレッド2もiの値を取得します。取得された値はスレッド1と等しく、スレッド2はに1を加算します。 iとそれを元に戻しますスレッド1もiに1を追加して元に戻します.putbackの値も等しく、これはi ++操作を実行する2つのスレッドに相当し、iの値は1だけ増加します。 iの値は100回の操作で100です。
2番目の極端なケース:スレッド1とスレッド2の間のインターバル操作、つまりスレッドペアi ++操作が完了し、1ずつインクリメントされたデータが戻された後、スレッド2が順番に操作され、最後に各スレッドが操作されます。 iに100回加算します。iの値は200です。
参照
プロセスにはグローバル変数iがあり、2つのスレッドがあります。I ++は2つのスレッドで100回実行されます。取得できる最大値と最小値は何ですか?