Compartir a través de


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!