この記事は機械翻訳のミラー記事です。元の記事にジャンプするにはこちらをクリックしてください。

眺める: 46741|答える: 7

[出典] ボラタイル vs. インターロック vs. ロック

[リンクをコピー]
掲載地 2018/08/27 14:40:35 | | |
複数のスレッドがアクセス可能な公開intカウンターフィールドを含むクラスがあり、この数は増減し続けるとします。

このフィールドを追加する際、以下のどのスキームを用いるべきで、その理由は?

  • lock(this.locker) this.counter++;
  • インターロック。インクリメント(参照 this.counter);
  • カウンターのアクセス修飾子をパブリックボラタイルに変更してください


最悪(どれも実際には効果がない)

カウンターのアクセス修飾子をパブリックボラタイルに変更してください

この方法は実際には全く安全ではなく、volatileのポイントは複数のCPU上で複数のスレッドがデータをバッファリングし、実行命令を並べ替えることです。

もし不揮発性の場合、CPUAが値だけ増加すると、CPUBはその値が増えるのを確認するまでしばらく待つ必要があり、これが問題を引き起こすことがあります。

揮発性であれば、両方のCPUが同時に同じ値を表示できるようにしています。 しかし、読み書き操作を横断するわけではありません。

変数に値を加えるには実際には3つのステップが必要です

1. 読書、2. 3を足す。書く

例えば、スレッドAがカウンターの値を1として読み取り、まだ増やす準備ができていない場合、スレッドBもカウンターの値を1として読み、両方のスレッドがインクリメンタルおよび書き込み操作を実行し始めるとします。 最終カウンターの値は2です。 これは正しくありません。両方のスレッドは増加操作を行っており、正しい結果は3であるはずです。 ですから、それを不安定だとラベル付けするのは単純に安全ではありません。

その方がいい

lock(this.locker) this.counter++;

こうすれば安全です(もちろん、このカウンターにアクセスする場所はすべてロックを忘れずに)。 これにより、他のスレッドがロックされたコードを実行するのを防ぎます。 また、上記のマルチCPU命令順序の問題も防げます。 問題はロックがパフォーマンスが遅く、他の無関係な場所でロックを使うと他のスレッドがブロックされてしまうことです。

ベスト

インターロック。インクリメント(参照 this.counter);

これは安全で非常に効率的です。 1つの原子で途中で中断されることなく、読み込み、増加、書き込みを3回実行します。 他のコードには影響しないので、他の場所でロックを覚える必要はありません。 また非常に高速です(MSDNによると、現代のCPUでは多くの場合、単なる命令です)。

しかし、CPUの命令順序の問題も解決できるのか、それともvolatileとこのインクリメントと併用する必要があるのかは完全にはわかりません。

補足:ボラタイルはどのような問題をうまく解決していますか?

ボラタイルはマルチスレッドを防げないのであれば、何ができるのでしょうか? 良い例としては、2つのスレッドがあり、1つは常に変数に書き込みます。例えば、その変数をqueneLengthとします。もう1つは常にこの変数からデータを読み込みます。 QueueLenghtが揮発性でない場合、スレッドAは5回読み込むかもしれませんが、スレッドBは遅延データや誤った順序でデータを認識することがあります。 一つの解決策はロックを使うことですが、この場合はボラタイルを使うこともできます。 これにより、スレッドBは常にスレッドAが書いた最新のデータを認識しますが、このロジックは書き込み時に読み取らない場合にのみ機能し、読み込むときに書き込まない場合に限られます。 複数のスレッドが読み書き・修正・書き込み操作を行いたい場合、Interlockedまたはlockを使う必要があります。





先の:Java MD5暗号化方法
次に:LinqはSQLの条件付きクエリで実装されています
掲載地 2018/08/29 16:21:42 |
こんにちは、先ほど作成したハイチャートの積み重ねヒストグラムとドリル可能なヒストグラムを組み合わせたコードですか? https://jshare.com.cn/demos/hhhhDz?hc-theme=grid-light インターフェースで編集できるコードを送ってもらえますか?
掲載地 2018/08/29 16:22:13 |
ネットワーク全体があなたのリソースです。
掲載地 2018/08/29 16:22:55 |
なぜなら、90年前の人々はメッセージを残すことができなかったからです。 だから
掲載地 2018/08/29 16:40:40 |
連絡先情報を追加するのは便利ですか? あなたに相談してください
 地主| 掲載地 2018/09/15 13:10:16 |
private static int safeInstanceCount = 0; 原子を扱う
System.Threading.Interlocked.Increment(ref safeInstanceCount); 自己増加 1
System.Threading.Interlocked.Decrement(ref safeInstanceCount); 自己マイナス1
掲載地 2020/05/21 16:43:54 |
所有者が共有できるよう応援しましょう
 地主| 掲載地 2020/06/11 15:00:16 |
1. コンセプト

マルチスレッド環境では、スレッドスケジューリング機構によって中断されない操作が、 この操作が始まると、コンテキストスイッチ(別のスレッドへの切り替え)なしに終了まで実行されます。

2. クラス

System.Threading.Interlocked static class(システム.スレッディング.インターロック)スタティッククラス

3. よく使われる関数(以下を参照)

1. public static int Decrement(参照 int 位置); 指定された変数の値を原子演算の形でデクラインし、その結果を保存します

lock(obj){i--; }

2.public static int Increment(参照 int 位置); 指定された変数の値を原子演算の形で増やし、その結果を保存します

lock(obj){i++; }
免責事項:
Code Farmer Networkが発行するすべてのソフトウェア、プログラミング資料、記事は学習および研究目的のみを目的としています。 上記の内容は商業的または違法な目的で使用されてはならず、そうでなければ利用者はすべての結果を負うことになります。 このサイトの情報はインターネットからのものであり、著作権紛争はこのサイトとは関係ありません。 ダウンロード後24時間以内に上記の内容を完全にパソコンから削除してください。 もしこのプログラムを気に入ったら、正規のソフトウェアを支持し、登録を購入し、より良い本物のサービスを受けてください。 もし侵害があれば、メールでご連絡ください。

Mail To:help@itsvse.com