lock ステートメント (C# リファレンス)lock Statement (C# Reference)
lock
キーワードは、ステートメント ブロックをクリティカル セクションとして指定します。このためには、特定のオブジェクトの相互排他ロックを取得し、ステートメントを実行して、ロックを解放します。The lock
keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock. 次の例では、lock
ステートメントが使用されています。The following example includes a lock
statement.
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
詳細については、「スレッドの同期」を参照してください。For more information, see Thread Synchronization.
コメントRemarks
lock
キーワードは、コードのクリティカル セクションに複数のスレッドが同時に進入することを防ぐ働きをします。The lock
keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. これから実行しようとしているコードがロックされている場合、別のスレッドは、そのオブジェクトが解放されるまで待機 (ブロック) 状態になります。If another thread tries to enter a locked code, it will wait, block, until the object is released.
スレッド処理については、「スレッド処理」を参照してください。The section Threading discusses threading.
lock
キーワードは、ブロックの先頭で Enter を呼び出し、ブロックの末尾で Exit を呼び出します。The lock
keyword calls Enter at the start of the block and Exit at the end of the block. lock
ステートメントの実行を待っているスレッドを Interrupt で中断すると、ThreadInterruptedException がスローされます。A ThreadInterruptedException is thrown if Interrupt interrupts a thread that is waiting to enter a lock
statement.
一般に、public
型 (つまり、コードの制御が及ばないインスタンス) をロックすることは避けてください。In general, avoid locking on a public
type, or instances beyond your code's control. lock (this)
、lock (typeof (MyType))
、lock ("myLock")
は、このガイドラインに違反する代表的なコンストラクトです。The common constructs lock (this)
, lock (typeof (MyType))
, and lock ("myLock")
violate this guideline:
lock (this)
は、このインスタンスにパブリックにアクセスできる場合に問題となります。lock (this)
is a problem if the instance can be accessed publicly.lock (typeof (MyType))
は、MyType
にパブリックにアクセスできる場合に問題となります。lock (typeof (MyType))
is a problem ifMyType
is publicly accessible.lock("myLock")
が問題となる理由は、同じ文字列を使用するコードがプロセス内に他にも存在した場合、そのコードも同じロックを共有するためです。lock("myLock")
is a problem because any other code in the process using the same string, will share the same lock.
private
オブジェクトを定義してロックの適用対象を限定するか、private static
オブジェクト変数を定義して、すべてのインスタンスに共通するデータを保護することをお勧めします。Best practice is to define a private
object to lock on, or a private static
object variable to protect data common to all instances.
lock
ステートメントの本体で await キーワードを使用することはできません。You can't use the await keyword in the body of a lock
statement.
例Example
次のサンプルでは、C# でロックされていないスレッドの簡単な使用例を示しています。The following sample shows a simple use of threads without locking in C#.
//using System.Threading;
class ThreadTest
{
public void RunMe()
{
Console.WriteLine("RunMe called");
}
static void Main()
{
ThreadTest b = new ThreadTest();
Thread t = new Thread(b.RunMe);
t.Start();
}
}
// Output: RunMe called
例Example
次のサンプルでは、スレッドと lock
を使用しています。The following sample uses threads and lock
. lock
ステートメントが存在する限り、このステートメント ブロックはクリティカル セクションとなり、balance
が負の数になることはありません。As long as the lock
statement is present, the statement block is a critical section and balance
will never become a negative number.
// using System.Threading;
class Account
{
private Object thisLock = new Object();
int balance;
Random r = new Random();
public Account(int initial)
{
balance = initial;
}
int Withdraw(int amount)
{
// This condition never is true unless the lock statement
// is commented out.
if (balance < 0)
{
throw new Exception("Negative Balance");
}
// Comment out the next line to see the effect of leaving out
// the lock keyword.
lock (thisLock)
{
if (balance >= amount)
{
Console.WriteLine("Balance before Withdrawal : " + balance);
Console.WriteLine("Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
}
else
{
return 0; // transaction rejected
}
}
}
public void DoTransactions()
{
for (int i = 0; i < 100; i++)
{
Withdraw(r.Next(1, 100));
}
}
}
class Test
{
static void Main()
{
Thread[] threads = new Thread[10];
Account acc = new Account(1000);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}
//block main thread until all other threads have ran to completion.
foreach (var t in threads)
t.Join();
}
}
C# 言語仕様C# Language Specification
詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。
関連項目See Also
MethodImplAttributes
Mutex
C# リファレンスC# Reference
C# プログラミング ガイドC# Programming Guide
スレッド化Threading
C# のキーワードC# Keywords
ステートメントのキーワードStatement Keywords
Monitor
インタロックされた操作Interlocked Operations
AutoResetEventAutoResetEvent
スレッドの同期Thread Synchronization