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

眺める: 20563|答える: 0

[出典] C#ロックキーワードは、特定のオブジェクトに対してミューテックスを取得して文を実行することで、文のブロックをクリティカル領域としてマークしますが...

[リンクをコピー]
掲載地 2015/12/31 17:51:01 | | |
ロックキーワードは、与えられたオブジェクトに対してミューテックスを取り、文を実行し、ロックを解放することで、文のブロックをクリティカルゾーンとしてマークします。

lock文は基本的にMonitor.EnterとMonitor.Exitを使用します。つまり、lock(this)が実行されたときにMonitor.Enter(this)が実行され、Monitor.Exit(this)がカール括弧の最後に実行されます。その意味は何ですか?任意のオブジェクトに対して、メモリの最初の部分はすべてのメソッドのアドレスであり、後半はインデックスです。 彼はCLRのSyncBlockキャッシュエリアにあるSyncBlockを指さします。それはどういう意味でしょうか? つまり、Monitor.Enter(Object)を実行する際に、オブジェクトのインデックス値が負の場合は、SyncBlockキャッシュからSyncBlockを選択し、そのアドレスをオブジェクトのインデックスに配置します。 これによりオブジェクトでマークされたロックが完了し、他のスレッドは再びMonitor.Enter(object)操作を実行し、正のオブジェクトのインデックスを取得して待機します。 インデックスが負になるまで、つまりスレッドはMonitor.Exit(object)を使ってインデックスを負に変えます。

ロックを使用する際に注意すべきこと:
1.ロックはnull値をロックできませんオブジェクトはnullを指し示すことができますが、nullを解放する必要はありません。 (関連項目:全零の理解)
2.lockは文字列型をロックできませんが、参照型でもあります。 文字列タイプはCLRによって「ホバー」されているためです
つまり、プログラム全体で任意の文字列のインスタンスは1つだけ存在し、その同じオブジェクトがすべての実行中のアプリケーションドメインのスレッドでそのテキストを表します。 したがって、アプリケーションプロセスのどこにいても同じ内容の文字列にロックがかけられている限り、アプリケーション内のその文字列のすべてのインスタンスはロックされます。 したがって、永続化されないプライベートまたは保護されたメンバーはロックするのが最善です。
3.locklock オブジェクトはプログラムブロックのメモリ境界です
4. 値型はロックできません。前のテキストで赤字で「オブジェクトが解放される」と表示されており、値型は参照型ではないからです
5.lockは、プログラムによって制御されていないパブリック型やオブジェクトのロックを回避します。
例えば、インスタンスが公開アクセス可能の場合、ロック(this)は制御されていないコードでもオブジェクトをロックできるため問題になることがあります。 これにより、同じオブジェクトを解放するために2つ以上のスレッドが同時に待つデッドロックが発生することがあります。 公開データ型(オブジェクトではなく)をロックすることも同じ理由で問題を引き起こすことがあります。
lock(this)を使う場合、クラスメンバー変数の値はクリティカルゾーンに属さないメソッドによって変更されることがあります

応用シナリオ:マルチスレッド操作による公開変数の値の不確実な例外を防ぎ、操作のセキュリティを確保するためによく用いられます

  1. // statements_lock2.cs
  2. using System;
  3. using System.Threading;

  4. class Account
  5. {
  6.     private Object thisLock = new Object();
  7.     int balance;

  8.     Random r = new Random();

  9.     public Account(int initial)
  10.     {
  11.         balance = initial;
  12.     }

  13.     int Withdraw(int amount)
  14.     {

  15.         // This condition will never be true unless the lock statement
  16.         // is commented out:
  17.         if (balance < 0)
  18.         {
  19.             throw new Exception("Negative Balance");
  20.         }

  21.         // Comment out the next line to see the effect of leaving out
  22.         // the lock keyword:
  23.         lock(thisLock)
  24.         {
  25.             if (balance >= amount)
  26.             {
  27.                 Console.WriteLine("Balance before Withdrawal :  " + balance);
  28.                 Console.WriteLine("Amount to Withdraw        : -" + amount);
  29.                 balance = balance - amount;
  30.                 Console.WriteLine("Balance after Withdrawal  :  " + balance);
  31.                 return amount;
  32.             }
  33.             else
  34.             {
  35.                 return 0; // transaction rejected
  36.             }
  37.         }
  38.     }

  39.     public void DoTransactions()
  40.     {
  41.         for (int i = 0; i < 100; i++)
  42.         {
  43.             Withdraw(r.Next(1, 100));
  44.         }
  45.     }
  46. }

  47. class Test
  48. {
  49.     static void Main()
  50.     {
  51.         Thread[] threads = new Thread[10];
  52.         Account acc = new Account(1000);
  53.         for (int i = 0; i < 10; i++)
  54.         {
  55.             Thread t = new Thread(new ThreadStart(acc.DoTransactions));
  56.             threads[i] = t;
  57.         }
  58.         for (int i = 0; i < 10; i++)
  59.         {
  60.             threads[i].Start();
  61.         }
  62.     }
  63. }
コードをコピーします








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

Mail To:help@itsvse.com