Antes de Java 5.0, solo había sincronizados (bloqueos integrados) y volátiles. Después de Java 5.0, se introdujo el bloqueo de pantalla ReentrantLock.
Descripción general de ReentrantLock
ReentrantLock es un bloqueo reentrante. Es diferente del bloqueo integrado. Requiere bloqueo y desbloqueo explícitos cada vez que se utiliza y proporciona funciones más avanzadas: bloqueo justo, bloqueo temporizado, bloqueo condicional y bloqueo sondeable. El bloqueo puede evitar eficazmente el problema de vida del punto muerto.
Interfaz de bloqueo:
Copie el código de código de la siguiente manera:
Bloqueo de interfaz pública {
//Bloquear hasta que se obtenga o interrumpa el bloqueo
bloqueo vacío();
//Bloquear hasta que se obtenga el bloqueo o se lance una excepción al interrumpir
void lockInterruptably() lanza InterruptedException;
// Obtener solo cuando el bloqueo esté disponible; de lo contrario, regresar directamente
tryLock booleano();
// Solo obtiene el bloqueo si está disponible dentro del tiempo especificado; de lo contrario, regresa directamente y arroja una excepción cuando se interrumpe
tryLock booleano (tiempo prolongado, unidad TimeUnit) arroja InterruptedException;
desbloqueo nulo();
//Devuelve una condición vinculada a este bloqueo
Condición nuevaCondición();
}
Uso de bloqueo
Copie el código de código de la siguiente manera:
Bloquear bloqueo = nuevo ReentrantLock();
lock.lock();
intentar{
//actualizar el estado del objeto
}finalmente{
//Tenga en cuenta que debe haber un bloque de código finalmente para desbloquear
// De lo contrario, es fácil provocar interbloqueos y otros problemas de actividad.
bloquear.desbloquear();
}
Funciones de bloqueo reentrante
Bloqueos de sondeo y bloqueos temporizados
Las solicitudes de bloqueo sondeables y cronometradas se implementan a través del método tryLock (), que es diferente de la adquisición incondicional de bloqueos. ReentrantLock puede tener un mecanismo flexible tolerante a fallas. Muchos casos de interbloqueo son causados por bloqueos secuenciales y diferentes subprocesos intentan adquirirlos. se bloquea al bloquear y no libera el bloqueo que ya tiene, lo que eventualmente provoca un punto muerto. Cuando el método tryLock () intenta obtener un bloqueo, si el bloqueo ya está retenido por otro subproceso, regresará inmediatamente de acuerdo con el método de configuración en lugar de bloquear y esperar. Al mismo tiempo, liberará el bloqueo que retiene. regresar Puede devolverlo de acuerdo con el resultado devuelto, se realiza un reintento o cancelación para evitar un punto muerto.
justicia
El constructor ReentrantLock proporciona dos opciones: bloqueo justo y bloqueo injusto (predeterminado). Los llamados bloqueos justos, los subprocesos adquirirán bloqueos en el orden en que emiten las solicitudes y no se permite el salto de cola, pero para los bloqueos injustos, se permite el salto de cola: cuando un subproceso solicita adquirir un bloqueo, si el bloqueo está disponible; Luego, este hilo omitirá el hilo en espera en la cola y adquirirá el bloqueo. Generalmente queremos que todos los bloqueos sean injustos. Porque al realizar operaciones de bloqueo, la equidad reducirá en gran medida el rendimiento debido a la sobrecarga de la suspensión y recuperación de subprocesos. Considere una situación: el hilo A mantiene un bloqueo, el hilo B solicita el bloqueo, por lo que el hilo B se suspende cuando el hilo A libera el bloqueo, el hilo B se activará, por lo que intenta adquirir el bloqueo nuevamente; C también solicita adquirir este bloqueo, entonces es probable que el subproceso C adquiera, use y libere este bloqueo antes de que el subproceso B se despierte por completo. Esta es una situación en la que todos ganan. En el momento en que B adquiere el bloqueo (B puede adquirir el bloqueo solo después de despertarse), C adquiere el bloqueo antes y el rendimiento también mejora. En la mayoría de los casos, el rendimiento de las cerraduras injustas es mayor que el de las cerraduras justas.
Las operaciones de adquisición de cerraduras se pueden interrumpir
El método lockInterruptfully adquiere el bloqueo sin dejar de responder a las interrupciones, por lo que no es necesario crear otros tipos de operaciones de bloqueo ininterrumpibles.
Bloqueo de lectura y escritura Bloqueo de lectura y escritura
ReentrantLock es un bloqueo mutex estándar. Solo un subproceso puede mantener el bloqueo a la vez. El bloqueo de lectura y escritura es diferente. Expone dos objetos Lock, uno de los cuales se usa para operaciones de lectura y el otro para operaciones de escritura.
Copie el código de código de la siguiente manera:
interfaz pública ReadWriteLock {
/**
* Devuelve el candado utilizado para la lectura.
*
* @return el candado utilizado para la lectura.
*/
Bloquear readLock();
/**
* Devuelve el candado utilizado para escribir.
*
* @return el candado utilizado para escribir.
*/
Bloquear writeLock();
}
Implementación opcional:
1. Prioridad de publicación
2. Leer saltos de hilo en línea
3. Reentrada
4.Bajar de categoría
5.Actualizar
ReentrantReadWriteLock implementa la interfaz ReadWriteLock y el constructor proporciona dos métodos de creación: bloqueo justo y bloqueo injusto. Los bloqueos de lectura y escritura son adecuados para situaciones en las que hay más lectura y menos escritura y pueden lograr una mejor concurrencia.
El código de copia de muestra es el siguiente:
clase pública ReadWriteMap<K, V> {
mapa privado<K, V> mapa;
bloqueo final privado ReadWriteLock = nuevo ReentrantReadWriteLock();
Bloqueo final privado readLock = lock.readLock();
Bloqueo final privado writeLock = lock.writeLock();
público ReadWriteMap (mapa <K, V> mapa) {
this.map = mapa;
}
público V get (tecla K) {
readLock.lock();
intentar {
devolver map.get(clave);
} finalmente {
readLock.desbloquear();
}
}
put vacío público (clave K, valor V) {
writeLock.lock();
intentar {
map.put(clave, valor);
} finalmente {
writeLock.desbloquear();
}
}
}