lock クラス
このクラスは、複数のスレッドからオブジェクトへのアクセスを同期するためのロックの取得を自動化します。 構築時にロックが取得され、破棄時にロックが解放されます。
構文
ref class lock;
解説
lock
は CLR オブジェクトに対してのみ使用でき、CLR コード内でのみ使用できます。
内部的には、lock クラスは Monitor を使用してアクセスを同期します。 詳細については、参照されている記事を参照してください。
メンバー
パブリック コンストラクター
名前 | 説明 |
---|---|
lock::lock | lock オブジェクトを構築し、必要に応じてロックの取得を無期限に、または指定した時間だけ待機するか、まったく待機しません。 |
lock::~lock | lock オブジェクトを破棄します。 |
パブリック メソッド
名前 | 説明 |
---|---|
lock::acquire | オブジェクトのロックを取得し、必要に応じてロックの取得を無期限に、または指定した時間だけ待機するか、まったく待機しません。 |
lock::is_locked | ロックが保持されているかどうかを示します。 |
lock::release | ロックを解放します。 |
lock::try_acquire | オブジェクトのロックを取得し、指定した時間待機した後 bool を返して、例外をスローする代わりに取得の成功を報告します。 |
パブリック演算子
名前 | 説明 |
---|---|
lock::operator bool | 条件式で lock を使用するための演算子。 |
lock::operator== | 等式演算子。 |
lock::operator!= | 非等値演算子。 |
要件
ヘッダー ファイル<msclr\lock.h>
名前空間 msclr
lock::lock
lock
オブジェクトを構築し、必要に応じてロックの取得を無期限に、または指定した時間だけ待機するか、まったく待機しません。
template<class T> lock(
T ^ _object
);
template<class T> lock(
T ^ _object,
int _timeout
);
template<class T> lock(
T ^ _object,
System::TimeSpan _timeout
);
template<class T> lock(
T ^ _object,
lock_later
);
パラメーター
_object
ロックするオブジェクト。
_timeout
ミリ秒単位または TimeSpan としてのタイムアウト値。
例外
タイムアウト前にロックの取得が行われない場合、ApplicationException をスローします。
解説
コンストラクターの最初の 3 つの形式では、_object
に対するロックを指定したタイムアウト期間内 (または何も指定していない場合は Infinite) に取得しようとします。
コンストラクターの 4 番目の形式では、_object
に対するロックが取得されません。 lock_later
は lock_when 列挙型のメンバーです。 この場合は、lock::acquire または lock::try_acquire を使用してロックを取得します。
ロックは、デストラクターが呼び出されたときに自動的に解放されます。
_object
を ReaderWriterLock にすることはできません。 そのようにすると、コンパイラ エラーが発生します。
例
この例では、クラスの単一インスタンスを複数のスレッドにわたって使用します。 このクラスは、自身に対してロックを使用して、内部データへのアクセスがスレッドごとに確実に一貫するようにします。 メイン アプリケーション スレッドでは、クラスの同じインスタンスに対してロックを使用して、ワーカー スレッドがまだ存在するかどうかが定期的に確認されます。 メイン アプリケーションは、すべてのワーカー スレッドがタスクを完了するまで、終了を待機します。
// msl_lock_lock.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
ref class CounterClass {
private:
int Counter;
public:
property int ThreadCount;
// function called by multiple threads, use lock to keep Counter consistent
// for each thread
void UseCounter() {
try {
lock l(this); // wait infinitely
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
for (int i = 0; i < 10; i++) {
Counter++;
Thread::Sleep(10);
}
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
Counter = 0;
// lock is automatically released when it goes out of scope and its destructor is called
}
catch (...) {
Console::WriteLine("Couldn't acquire lock!");
}
ThreadCount--;
}
};
int main() {
// create a few threads to contend for access to the shared data
CounterClass^ cc = gcnew CounterClass;
array<Thread^>^ tarr = gcnew array<Thread^>(5);
ThreadStart^ startDelegate = gcnew ThreadStart(cc, &CounterClass::UseCounter);
for (int i = 0; i < tarr->Length; i++) {
tarr[i] = gcnew Thread(startDelegate);
cc->ThreadCount++;
tarr[i]->Start();
}
// keep our main thread alive until all worker threads have completed
lock l(cc, lock_later); // don't lock now, just create the object
while (true) {
if (l.try_acquire(50)) { // try to acquire lock, don't throw an exception if can't
if (0 == cc->ThreadCount) {
Console::WriteLine("All threads completed.");
break; // all threads are gone, exit while
}
else {
Console::WriteLine("{0} threads exist, continue waiting...", cc->ThreadCount);
l.release(); // some threads exist, let them do their work
}
}
}
}
In thread 3, Counter = 0
In thread 3, Counter = 10
In thread 5, Counter = 0
In thread 5, Counter = 10
In thread 7, Counter = 0
In thread 7, Counter = 10
In thread 4, Counter = 0
In thread 4, Counter = 10
In thread 6, Counter = 0
In thread 6, Counter = 10
All threads completed.
lock::~lock
lock
オブジェクトを破棄します。
~lock();
解説
このデストラクターは lock::release を呼び出します。
例
この例では、クラスの単一インスタンスを複数のスレッドにわたって使用します。 このクラスは、自身に対してロックを使用して、内部データへのアクセスがスレッドごとに確実に一貫するようにします。 メイン アプリケーション スレッドでは、クラスの同じインスタンスに対してロックを使用して、ワーカー スレッドがまだ存在するかどうかが定期的に確認されます。 メイン アプリケーションは、すべてのワーカー スレッドがタスクを完了するまで、終了を待機します。
// msl_lock_dtor.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
ref class CounterClass {
private:
int Counter;
public:
property int ThreadCount;
// function called by multiple threads, use lock to keep Counter consistent
// for each thread
void UseCounter() {
try {
lock l(this); // wait infinitely
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
for (int i = 0; i < 10; i++) {
Counter++;
Thread::Sleep(10);
}
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
Counter = 0;
// lock is automatically released when it goes out of scope and its destructor is called
}
catch (...) {
Console::WriteLine("Couldn't acquire lock!");
}
ThreadCount--;
}
};
int main() {
// create a few threads to contend for access to the shared data
CounterClass^ cc = gcnew CounterClass;
array<Thread^>^ tarr = gcnew array<Thread^>(5);
ThreadStart^ startDelegate = gcnew ThreadStart(cc, &CounterClass::UseCounter);
for (int i = 0; i < tarr->Length; i++) {
tarr[i] = gcnew Thread(startDelegate);
cc->ThreadCount++;
tarr[i]->Start();
}
// keep our main thread alive until all worker threads have completed
lock l(cc, lock_later); // don't lock now, just create the object
while (true) {
if (l.try_acquire(50)) { // try to acquire lock, don't throw an exception if can't
if (0 == cc->ThreadCount) {
Console::WriteLine("All threads completed.");
break; // all threads are gone, exit while
}
else {
Console::WriteLine("{0} threads exist, continue waiting...", cc->ThreadCount);
l.release(); // some threads exist, let them do their work
}
}
}
}
In thread 3, Counter = 0
In thread 3, Counter = 10
In thread 5, Counter = 0
In thread 5, Counter = 10
In thread 7, Counter = 0
In thread 7, Counter = 10
In thread 4, Counter = 0
In thread 4, Counter = 10
In thread 6, Counter = 0
In thread 6, Counter = 10
All threads completed.
lock::acquire
オブジェクトのロックを取得し、必要に応じてロックの取得を無期限に、または指定した時間だけ待機するか、まったく待機しません。
void acquire();
void acquire(
int _timeout
);
void acquire(
System::TimeSpan _timeout
);
パラメーター
_timeout
ミリ秒単位または TimeSpan としてのタイムアウト値。
例外
タイムアウト前にロックの取得が行われない場合、ApplicationException をスローします。
解説
タイムアウト値が指定されていない場合、既定のタイムアウトは Infinite です。
ロックが既に取得されている場合、この関数は何も行いません。
例
この例では、クラスの単一インスタンスを複数のスレッドにわたって使用します。 このクラスは、自身に対してロックを使用して、内部データへのアクセスがスレッドごとに確実に一貫するようにします。 メイン アプリケーション スレッドでは、クラスの同じインスタンスに対してロックを使用して、ワーカー スレッドがまだ存在するかどうかが定期的に確認されます。 メイン アプリケーションは、すべてのワーカー スレッドがタスクを完了するまで、終了を待機します。
// msl_lock_acquire.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
ref class CounterClass {
private:
int Counter;
public:
property int ThreadCount;
// function called by multiple threads, use lock to keep Counter consistent
// for each thread
void UseCounter() {
try {
lock l(this); // wait infinitely
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
for (int i = 0; i < 10; i++) {
Counter++;
Thread::Sleep(10);
}
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
Counter = 0;
// lock is automatically released when it goes out of scope and its destructor is called
}
catch (...) {
Console::WriteLine("Couldn't acquire lock!");
}
ThreadCount--;
}
};
int main() {
// create a few threads to contend for access to the shared data
CounterClass^ cc = gcnew CounterClass;
array<Thread^>^ tarr = gcnew array<Thread^>(5);
ThreadStart^ startDelegate = gcnew ThreadStart(cc, &CounterClass::UseCounter);
for (int i = 0; i < tarr->Length; i++) {
tarr[i] = gcnew Thread(startDelegate);
cc->ThreadCount++;
tarr[i]->Start();
}
// keep our main thread alive until all worker threads have completed
lock l(cc, lock_later); // don't lock now, just create the object
while (true) {
if (l.try_acquire(50)) { // try to acquire lock, don't throw an exception if can't
if (0 == cc->ThreadCount) {
Console::WriteLine("All threads completed.");
break; // all threads are gone, exit while
}
else {
Console::WriteLine("{0} threads exist, continue waiting...", cc->ThreadCount);
l.release(); // some threads exist, let them do their work
}
}
}
}
In thread 3, Counter = 0
In thread 3, Counter = 10
In thread 5, Counter = 0
In thread 5, Counter = 10
In thread 7, Counter = 0
In thread 7, Counter = 10
In thread 4, Counter = 0
In thread 4, Counter = 10
In thread 6, Counter = 0
In thread 6, Counter = 10
All threads completed.
lock::is_locked
ロックが保持されているかどうかを示します。
bool is_locked();
戻り値
ロックが保持されている場合は true
。それ以外の場合は false
。
例
この例では、クラスの単一インスタンスを複数のスレッドにわたって使用します。 このクラスは、自身に対してロックを使用して、内部データへのアクセスがスレッドごとに確実に一貫するようにします。 メイン アプリケーション スレッドは、クラスの同じインスタンスに対してロックを使用して、ワーカー スレッドがまだ存在するかどうかを定期的に確認し、すべてのワーカー スレッドがそのタスクを完了するまで終了を待機します。
// msl_lock_is_locked.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
ref class CounterClass {
private:
int Counter;
public:
property int ThreadCount;
// function called by multiple threads, use lock to keep Counter consistent
// for each thread
void UseCounter() {
try {
lock l(this); // wait infinitely
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
for (int i = 0; i < 10; i++) {
Counter++;
Thread::Sleep(10);
}
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
Counter = 0;
// lock is automatically released when it goes out of scope and its destructor is called
}
catch (...) {
Console::WriteLine("Couldn't acquire lock!");
}
ThreadCount--;
}
};
int main() {
// create a few threads to contend for access to the shared data
CounterClass^ cc = gcnew CounterClass;
array<Thread^>^ tarr = gcnew array<Thread^>(5);
ThreadStart^ startDelegate = gcnew ThreadStart(cc, &CounterClass::UseCounter);
for (int i = 0; i < tarr->Length; i++) {
tarr[i] = gcnew Thread(startDelegate);
cc->ThreadCount++;
tarr[i]->Start();
}
// keep our main thread alive until all worker threads have completed
lock l(cc, lock_later); // don't lock now, just create the object
while (true) {
l.try_acquire(50); // try to acquire lock, don't throw an exception if can't
if (l.is_locked()) { // check if we got the lock
if (0 == cc->ThreadCount) {
Console::WriteLine("All threads completed.");
break; // all threads are gone, exit while
}
else {
Console::WriteLine("{0} threads exist, continue waiting...", cc->ThreadCount);
l.release(); // some threads exist, let them do their work
}
}
}
}
In thread 3, Counter = 0
In thread 3, Counter = 10
In thread 5, Counter = 0
In thread 5, Counter = 10
In thread 4, Counter = 0
In thread 4, Counter = 10
In thread 7, Counter = 0
In thread 7, Counter = 10
In thread 6, Counter = 0
In thread 6, Counter = 10
All threads completed.
lock::operator bool
条件式で lock
を使用するための演算子。
operator bool();
戻り値
ロックが保持されている場合は true
。それ以外の場合は false
。
解説
この演算子は、整数型に変換できないため、実際には bool
より安全な _detail_class::_safe_bool
に変換されます。
例
この例では、クラスの単一インスタンスを複数のスレッドにわたって使用します。 このクラスは、自身に対してロックを使用して、内部データへのアクセスがスレッドごとに確実に一貫するようにします。 メイン アプリケーション スレッドでは、クラスの同じインスタンスに対してロックを使用して、ワーカー スレッドがまだ存在するかどうかが定期的に確認されます。 メイン アプリケーションは、すべてのワーカー スレッドがタスクを完了するまで、終了を待機します。
// msl_lock_op_bool.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
ref class CounterClass {
private:
int Counter;
public:
property int ThreadCount;
// function called by multiple threads, use lock to keep Counter consistent
// for each thread
void UseCounter() {
try {
lock l(this); // wait infinitely
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
for (int i = 0; i < 10; i++) {
Counter++;
Thread::Sleep(10);
}
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
Counter = 0;
// lock is automatically released when it goes out of scope and its destructor is called
}
catch (...) {
Console::WriteLine("Couldn't acquire lock!");
}
ThreadCount--;
}
};
int main() {
// create a few threads to contend for access to the shared data
CounterClass^ cc = gcnew CounterClass;
array<Thread^>^ tarr = gcnew array<Thread^>(5);
ThreadStart^ startDelegate = gcnew ThreadStart(cc, &CounterClass::UseCounter);
for (int i = 0; i < tarr->Length; i++) {
tarr[i] = gcnew Thread(startDelegate);
cc->ThreadCount++;
tarr[i]->Start();
}
// keep our main thread alive until all worker threads have completed
lock l(cc, lock_later); // don't lock now, just create the object
while (true) {
l.try_acquire(50); // try to acquire lock, don't throw an exception if can't
if (l) { // use bool operator to check for lock
if (0 == cc->ThreadCount) {
Console::WriteLine("All threads completed.");
break; // all threads are gone, exit while
}
else {
Console::WriteLine("{0} threads exist, continue waiting...", cc->ThreadCount);
l.release(); // some threads exist, let them do their work
}
}
}
}
In thread 3, Counter = 0
In thread 3, Counter = 10
In thread 5, Counter = 0
In thread 5, Counter = 10
In thread 7, Counter = 0
In thread 7, Counter = 10
In thread 4, Counter = 0
In thread 4, Counter = 10
In thread 6, Counter = 0
In thread 6, Counter = 10
All threads completed.
lock::release
ロックを解放します。
void release();
解説
ロックが保持されていない場合、release
は何も行いません。
この関数を明示的に呼び出す必要はありません。 lock
オブジェクトがスコープ外に出ると、そのデストラクターは release
を呼び出します。
例
この例では、クラスの単一インスタンスを複数のスレッドにわたって使用します。 このクラスは、自身に対してロックを使用して、内部データへのアクセスがスレッドごとに確実に一貫するようにします。 メイン アプリケーション スレッドでは、クラスの同じインスタンスに対してロックを使用して、ワーカー スレッドがまだ存在するかどうかが定期的に確認されます。 メイン アプリケーションは、すべてのワーカー スレッドがタスクを完了するまで、終了を待機します。
// msl_lock_release.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
ref class CounterClass {
private:
int Counter;
public:
property int ThreadCount;
// function called by multiple threads, use lock to keep Counter consistent
// for each thread
void UseCounter() {
try {
lock l(this); // wait infinitely
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
for (int i = 0; i < 10; i++) {
Counter++;
Thread::Sleep(10);
}
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
Counter = 0;
// lock is automatically released when it goes out of scope and its destructor is called
}
catch (...) {
Console::WriteLine("Couldn't acquire lock!");
}
ThreadCount--;
}
};
int main() {
// create a few threads to contend for access to the shared data
CounterClass^ cc = gcnew CounterClass;
array<Thread^>^ tarr = gcnew array<Thread^>(5);
ThreadStart^ startDelegate = gcnew ThreadStart(cc, &CounterClass::UseCounter);
for (int i = 0; i < tarr->Length; i++) {
tarr[i] = gcnew Thread(startDelegate);
cc->ThreadCount++;
tarr[i]->Start();
}
// keep our main thread alive until all worker threads have completed
lock l(cc, lock_later); // don't lock now, just create the object
while (true) {
if (l.try_acquire(50)) { // try to acquire lock, don't throw an exception if can't
if (0 == cc->ThreadCount) {
Console::WriteLine("All threads completed.");
break; // all threads are gone, exit while
}
else {
Console::WriteLine("{0} threads exist, continue waiting...", cc->ThreadCount);
l.release(); // some threads exist, let them do their work
}
}
}
}
In thread 3, Counter = 0
In thread 3, Counter = 10
In thread 5, Counter = 0
In thread 5, Counter = 10
In thread 7, Counter = 0
In thread 7, Counter = 10
In thread 4, Counter = 0
In thread 4, Counter = 10
In thread 6, Counter = 0
In thread 6, Counter = 10
All threads completed.
lock::try_acquire
オブジェクトのロックを取得し、指定した時間待機した後 bool
を返して、例外をスローする代わりに取得の成功を報告します。
bool try_acquire(
int _timeout_ms
);
bool try_acquire(
System::TimeSpan _timeout
);
パラメーター
_timeout
ミリ秒単位または TimeSpan としてのタイムアウト値。
戻り値
ロックが取得された場合は true
。それ以外の場合は false
。
解説
ロックが既に取得されている場合、この関数は何も行いません。
例
この例では、クラスの単一インスタンスを複数のスレッドにわたって使用します。 このクラスは、自身に対してロックを使用して、内部データへのアクセスがスレッドごとに確実に一貫するようにします。 メイン アプリケーション スレッドでは、クラスの同じインスタンスに対してロックを使用して、ワーカー スレッドがまだ存在するかどうかが定期的に確認されます。 メイン アプリケーションは、すべてのワーカー スレッドがタスクを完了するまで、終了を待機します。
// msl_lock_try_acquire.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
ref class CounterClass {
private:
int Counter;
public:
property int ThreadCount;
// function called by multiple threads, use lock to keep Counter consistent
// for each thread
void UseCounter() {
try {
lock l(this); // wait infinitely
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
for (int i = 0; i < 10; i++) {
Counter++;
Thread::Sleep(10);
}
Console::WriteLine("In thread {0}, Counter = {1}", Thread::CurrentThread->ManagedThreadId,
Counter);
Counter = 0;
// lock is automatically released when it goes out of scope and its destructor is called
}
catch (...) {
Console::WriteLine("Couldn't acquire lock!");
}
ThreadCount--;
}
};
int main() {
// create a few threads to contend for access to the shared data
CounterClass^ cc = gcnew CounterClass;
array<Thread^>^ tarr = gcnew array<Thread^>(5);
ThreadStart^ startDelegate = gcnew ThreadStart(cc, &CounterClass::UseCounter);
for (int i = 0; i < tarr->Length; i++) {
tarr[i] = gcnew Thread(startDelegate);
cc->ThreadCount++;
tarr[i]->Start();
}
// keep our main thread alive until all worker threads have completed
lock l(cc, lock_later); // don't lock now, just create the object
while (true) {
if (l.try_acquire(50)) { // try to acquire lock, don't throw an exception if can't
if (0 == cc->ThreadCount) {
Console::WriteLine("All threads completed.");
break; // all threads are gone, exit while
}
else {
Console::WriteLine("{0} threads exist, continue waiting...", cc->ThreadCount);
l.release(); // some threads exist, let them do their work
}
}
}
}
In thread 3, Counter = 0
In thread 3, Counter = 10
In thread 5, Counter = 0
In thread 5, Counter = 10
In thread 7, Counter = 0
In thread 7, Counter = 10
In thread 4, Counter = 0
In thread 4, Counter = 10
In thread 6, Counter = 0
In thread 6, Counter = 10
All threads completed.
lock::operator==
等式演算子。
template<class T> bool operator==(
T t
);
パラメーター
t
等しいかどうかを比較するオブジェクト。
戻り値
t
がロックのオブジェクトと同じ場合は true
、そうでない場合は false
を返します。
例
// msl_lock_op_eq.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
int main () {
Object^ o1 = gcnew Object;
lock l1(o1);
if (l1 == o1) {
Console::WriteLine("Equal!");
}
}
Equal!
lock::operator!=
非等値演算子。
template<class T> bool operator!=(
T t
);
パラメーター
t
等しくないかどうかを比較するオブジェクト。
戻り値
t
がロックのオブジェクトと異なる場合は true
、そうでない場合は false
を返します。
例
// msl_lock_op_ineq.cpp
// compile with: /clr
#include <msclr/lock.h>
using namespace System;
using namespace System::Threading;
using namespace msclr;
int main () {
Object^ o1 = gcnew Object;
Object^ o2 = gcnew Object;
lock l1(o1);
if (l1 != o2) {
Console::WriteLine("Inequal!");
}
}
Inequal!