lock (Clase)
Esta clase automatiza la toma de un bloqueo para sincronizar el acceso a un objeto desde varios subprocesos. Cuando se construye, adquiere el bloqueo y, cuando se destruye, lo libera.
Sintaxis
ref class lock;
Comentarios
lock
solo está disponible para objetos de CLR y solo se puede usar en el código de CLR.
Internamente, la clase de bloqueo usa Monitor para sincronizar el acceso. Para obtener más información, vea el artículo al que se hace referencia.
Miembros
Constructores públicos
Nombre | Descripción |
---|---|
lock::lock | Construye un objeto lock , opcionalmente esperando adquirir el bloqueo para siempre, durante un periodo de tiempo especificado, o no lo hace en absoluto. |
lock::~lock | Destruye un objeto lock . |
Métodos públicos
Nombre | Descripción |
---|---|
lock::acquire | Adquiere un bloqueo en un objeto, opcionalmente esperando adquirir el bloqueo para siempre, durante un periodo de tiempo especificado, o no lo hace en absoluto. |
lock::is_locked | Indica si se mantiene un bloqueo. |
lock::release | Libera un bloqueo. |
lock::try_acquire | Adquiere un bloqueo en un objeto, esperando una cantidad determinada de tiempo y devolviendo un objeto bool para notificar el éxito de la adquisición en lugar de producir una excepción. |
Operadores públicos
Nombre | Descripción |
---|---|
lock::operator bool | Operador para usar lock en una expresión condicional. |
lock::operator== | Operador de igualdad. |
lock::operator!= | Operador de desigualdad. |
Requisitos
Archivo de encabezado<msclr\lock.h>
Espacio de nombres msclr
lock::lock
Construye un objeto lock
, opcionalmente esperando adquirir el bloqueo para siempre, durante un periodo de tiempo especificado, o no lo hace en absoluto.
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
);
Parámetros
_object
Objeto que se va a bloquear.
_timeout
Valor del tiempo de espera en milisegundos, o como un elemento TimeSpan.
Excepciones
Genera ApplicationException si la adquisición del bloqueo no se produce antes del tiempo de espera.
Comentarios
Las tres primeras formas del constructor intentan adquirir un bloqueo en _object
dentro del periodo de tiempo de espera especificado (o Infinite si no se especifica ninguno).
La cuarta forma del constructor no adquiere un bloqueo en _object
. lock_later
es miembro de la enumeración lock_when. Use lock::acquire o lock::try_acquire para adquirir el bloqueo en este caso.
El bloqueo se liberará automáticamente cuando se llame al destructor.
_object
no puede ser ReaderWriterLock. Si es así, se producirá un error del compilador.
Ejemplo
En este ejemplo se usa una sola instancia de una clase en varios subprocesos. La clase usa un bloqueo en sí mismo para asegurarse de que los accesos a sus datos internos son coherentes para cada subproceso. El subproceso de aplicación principal usa un bloqueo en la misma instancia de la clase para comprobar periódicamente si todavía existen subprocesos de trabajo. Después, la aplicación principal espera hasta que todos los subprocesos de trabajo hayan completado sus tareas para salir.
// 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
Destruye un objeto lock
.
~lock();
Comentarios
El destructor llama a lock::release.
Ejemplo
En este ejemplo se usa una sola instancia de una clase en varios subprocesos. La clase usa un bloqueo en sí mismo para asegurarse de que los accesos a sus datos internos son coherentes para cada subproceso. El subproceso de aplicación principal usa un bloqueo en la misma instancia de la clase para comprobar periódicamente si todavía existen subprocesos de trabajo. Después, la aplicación principal espera hasta que todos los subprocesos de trabajo hayan completado sus tareas para salir.
// 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
Adquiere un bloqueo en un objeto, opcionalmente esperando adquirir el bloqueo para siempre, durante un periodo de tiempo especificado, o no lo hace en absoluto.
void acquire();
void acquire(
int _timeout
);
void acquire(
System::TimeSpan _timeout
);
Parámetros
_timeout
Valor del tiempo de espera en milisegundos, o como un elemento TimeSpan.
Excepciones
Genera ApplicationException si la adquisición del bloqueo no se produce antes del tiempo de espera.
Comentarios
Si no se proporciona un valor de tiempo de espera, será Infinite de manera predeterminada.
Si ya se ha adquirido un bloqueo, esta función no hace nada.
Ejemplo
En este ejemplo se usa una sola instancia de una clase en varios subprocesos. La clase usa un bloqueo en sí mismo para asegurarse de que los accesos a sus datos internos son coherentes para cada subproceso. El subproceso de aplicación principal usa un bloqueo en la misma instancia de la clase para comprobar periódicamente si todavía existen subprocesos de trabajo. Después, la aplicación principal espera hasta que todos los subprocesos de trabajo hayan completado sus tareas para salir.
// 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
Indica si se mantiene un bloqueo.
bool is_locked();
Valor devuelto
Es true
si se mantiene un bloqueo; de lo contrario, es false
.
Ejemplo
En este ejemplo se usa una sola instancia de una clase en varios subprocesos. La clase usa un bloqueo en sí mismo para asegurarse de que los accesos a sus datos internos son coherentes para cada subproceso. El subproceso de aplicación principal usa un bloqueo en la misma instancia de la clase para comprobar periódicamente si todavía existen subprocesos de trabajo y espera hasta que todos los subprocesos de trabajo hayan completado sus tareas para salir.
// 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
Operador para usar lock
en una expresión condicional.
operator bool();
Valor devuelto
Es true
si se mantiene un bloqueo; de lo contrario, es false
.
Comentarios
Este operador se convierte en _detail_class::_safe_bool
, que es más seguro que bool
ya que no se puede convertir en un tipo entero.
Ejemplo
En este ejemplo se usa una sola instancia de una clase en varios subprocesos. La clase usa un bloqueo en sí mismo para asegurarse de que los accesos a sus datos internos son coherentes para cada subproceso. El subproceso de aplicación principal usa un bloqueo en la misma instancia de la clase para comprobar periódicamente si todavía existen subprocesos de trabajo. La aplicación principal espera hasta que todos los subprocesos de trabajo hayan completado sus tareas para salir.
// 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
Libera un bloqueo.
void release();
Comentarios
Si no se mantiene ningún bloqueo, release
no hace nada.
No es necesario llamar explícitamente a esta función. Cuando un objeto lock
sale del ámbito, su destructor llama a release
.
Ejemplo
En este ejemplo se usa una sola instancia de una clase en varios subprocesos. La clase usa un bloqueo en sí mismo para asegurarse de que los accesos a sus datos internos son coherentes para cada subproceso. El subproceso de aplicación principal usa un bloqueo en la misma instancia de la clase para comprobar periódicamente si todavía existen subprocesos de trabajo. Después, la aplicación principal espera hasta que todos los subprocesos de trabajo hayan completado sus tareas para salir.
// 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
Adquiere un bloqueo en un objeto, esperando una cantidad determinada de tiempo y devolviendo un objeto bool
para notificar el éxito de la adquisición en lugar de producir una excepción.
bool try_acquire(
int _timeout_ms
);
bool try_acquire(
System::TimeSpan _timeout
);
Parámetros
_timeout
Valor del tiempo de espera en milisegundos, o como un elemento TimeSpan.
Valor devuelto
Es true
si se ha adquirido el bloqueo; de lo contrario, es false
.
Comentarios
Si ya se ha adquirido un bloqueo, esta función no hace nada.
Ejemplo
En este ejemplo se usa una sola instancia de una clase en varios subprocesos. La clase usa un bloqueo en sí mismo para asegurarse de que los accesos a sus datos internos son coherentes para cada subproceso. El subproceso de aplicación principal usa un bloqueo en la misma instancia de la clase para comprobar periódicamente si todavía existen subprocesos de trabajo. Después, la aplicación principal espera hasta que todos los subprocesos de trabajo hayan completado sus tareas para salir.
// 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==
Operador de igualdad.
template<class T> bool operator==(
T t
);
Parámetros
t
Objeto que se va a comparar para obtener igualdad.
Valor devuelto
Devuelve true
si t
es el mismo que el objeto del bloqueo; de lo contrario, devuelve false
.
Ejemplo
// 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!=
Operador de desigualdad.
template<class T> bool operator!=(
T t
);
Parámetros
t
Objeto cuya desigualdad se va a comparar.
Valor devuelto
Devuelve true
si t
difiere del objeto del bloqueo; de lo contrario, devuelve false
.
Ejemplo
// 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!