Класс lock
Этот класс автоматизирует синхронизацию доступа к объекту из нескольких потоков. При построении он получает блокировку и при уничтожении освобождает блокировку.
Синтаксис
ref class lock;
Замечания
lock
доступен только для объектов СРЕДЫ CLR и может использоваться только в коде СРЕДЫ CLR.
Внутри этого класса блокировки используется 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
);
Параметры
_объект
Объект, который нужно заблокировать.
_Времени ожидания
Время ожидания в миллисекундах или в виде TimeSpan.
Исключения
Вызывается ApplicationException , если приобретение блокировки не происходит до истечения времени ожидания.
Замечания
Первые три формы конструктора пытаются получить блокировку _object
в течение указанного периода времени ожидания (или Infinite если он не указан).
Четвертая форма конструктора не получает блокировку _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
);
Параметры
_Времени ожидания
Значение времени ожидания в миллисекундах или в виде 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
в противном случае.
Замечания
Этот оператор фактически преобразуется в _detail_class::_safe_bool
более безопасный, чем 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
);
Параметры
_Времени ожидания
Значение времени ожидания в миллисекундах или в виде 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
объект блокировки совпадает 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
);
Параметры
с
Объект для сравнения с неравенством.
Возвращаемое значение
Возвращает значение true
, если t
отличается от объекта блокировки, 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!