son - Desbloqueo de bloqueo propiedad de otro hilo java.
metodos de hilos en java (5)
¿Por qué no simplemente envuelve el código de su hilo alrededor de lo siguiente?
ReentrantLock lock = ... obtain your lock somehow ...
lock.lock();
try {
... the "bad boy" code here ...
} finally {
lock.unlock();
}
Luego, cuando su hilo termine (ya sea normalmente terminando o lanzando una excepción de su "muerte"), se liberará el bloqueo.
Esta es realmente la manera en que Oracle recomienda usar ReentrantLock: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html
Tengo un LockManager que gestiona los bloqueos de varios subprocesos. A veces, los hilos son malos, y tengo que matarlos y pedirle al LockManager que libere todos sus bloqueos. Sin embargo, ya que uso ReentrantLock en Java, esto es imposible, no puedo desbloquear un bloqueo que pertenece a otro hilo.
Me veo forzado a usar Cerraduras (no puedo usar semáforos, es el punto de la tarea). ¿Hay alguna implementación de bloqueo de Java que me permita desbloquear los bloqueos que pertenecen a otros subprocesos?
Hasta ahora las opciones que he considerado son:
- Re-implementando ReentrantLock de una manera que me permita hacer esto
- Haz algún tipo de mapeo entre Semaphores y ReentrantLocks
Fuentes adicionales que pueden ser útiles:
Como se indica en los comentarios, matar hilos no es una buena práctica. La mayoría de los marcos hacen todo lo posible para interrumpir los subprocesos en las colas de trabajo, pero solo tendrán efecto si el código ejecutado comprueba el indicador de interrupción, ya sea llamando a Thread.isInterrupted()
o llamando a un método de IO o bloqueo interrumpible.
Si realmente necesita el concepto de matar la ejecución de código, eche un vistazo a la clase Process
. Puede crear un Process
llamando a Runtime.exec()
o utilizando ProcessBuilder
. Llamar a Process.destroyForcibly()
terminará por la fuerza el proceso en ejecución.
Has descubierto una razón importante por la que la sabiduría común dice: ¡No mates los hilos!
Los bloqueos son solo una de las posibles fugas de recursos que pueden suceder si mata un hilo por la fuerza. Considera archivos abiertos y sockets, etc.
También tenga en cuenta que si logró desbloquear el bloqueo, hubo una razón por la que el bloqueo se bloqueó en primer lugar. Por ejemplo, el subproceso puede haber actualizado parcialmente una estructura de datos, y permitir el acceso a esa estructura desde otro subproceso puede causar fallas extrañas y maravillosas en los programas que son difíciles, si no imposibles, de depurar.
La mejor manera de manejar esta situación es pedir que el hilo desaparezca. Agregue un método "stop ()" al objeto asociado con el hilo (tiene un objeto para cada hilo, ¿no es así?) Que establece un indicador, y haga que el hilo verifique este indicador con regularidad y salga si está establecido .
Si los subprocesos se comportan mal de una manera que les impide verificar el indicador de parada, el enfoque correcto es corregir el código para que no se comporte mal.
He hecho esto con una referencia atómica que obtiene cero puntos por elegancia, pero no conozco otra manera.
class PseudoLock {
private final AtomicReference<Boolean> mylock = new AtomicReference<>(Boolean.FALSE);
boolean trylock() {
return mylock.compareAndSet(Boolean.FALSE, Boolean.TRUE);
}
void unlock() {
boolean done = mylock.compareAndSet(Boolean.TRUE, Boolean.FALSE);
if (!done) {
throw new IllegalStateException("Cannot unlock an unlocked thread");
}
}
}
'''' ''''
¿Podrías usar tu propio Lock
? Aquí hay una clase que proxies completamente el Lock
pero cuando se le pide que fuerce el desbloqueo, simplemente reemplaza el bloqueo que se está procesando con uno nuevo. Esto debería tener el efecto que desea. Lamentablemente, todavía no se ocupa de los bloqueos que quedan colgando, pero ahora se convierte en un problema de otra persona. Tus cerraduras ahora están desbloqueadas mágicamente.
static class LockProxy<L extends Lock> implements Lock {
// The actual lock.
private volatile Lock lock;
public LockProxy(L lock) {
// Trap the lock we are proxying.
this.lock = lock;
}
@Override
public void lock() {
// Proxy it.
lock.lock();
}
@Override
public void lockInterruptibly() throws InterruptedException {
// Proxy it.
lock.lockInterruptibly();
}
@Override
public boolean tryLock() {
// Proxy it.
return lock.tryLock();
}
@Override
public boolean tryLock(long l, TimeUnit tu) throws InterruptedException {
// Proxy it.
return lock.tryLock(l, tu);
}
@Override
public void unlock() {
// Proxy it.
lock.unlock();
}
@Override
public Condition newCondition() {
// Proxy it.
return lock.newCondition();
}
// Extra functionality to unlock from any thread.
public void forceUnlock() {
// Actually just replace the perhaps locked lock with a new one.
// Kinda like a clone. I expect a neater way is around somewhere.
if (lock instanceof ReentrantLock) {
lock = new ReentrantLock();
} else {
throw new UnsupportedOperationException(
"Cannot force unlock of lock type "
+ lock.getClass().getSimpleName());
}
}
}