Pregunta

¿Qué es la implementación Reentrantlock#Trylock (Long, TimeUnit) cuando intenta acumular un bloqueo? Suponga que el subproceso es posee el bloqueo de myLock, y hilo B LLAMADA myLock.tryLock(10,SECONDS), ¿está durmiendo o esperando el hilo B?

En otras palabras, fue la diferencia de estas 2 implementaciones:

1.

while (true)
   try {
     if (readLock.tryLock())
       return;
     MILLISECONDS.sleep(5);
   }catch (InterruptedException e) {}

2.

 while (true)
   try {
     if (readLock.tryLock(5,MILLISECONDS))
       return;
   }catch (InterruptedException e) {}
¿Fue útil?

Solución

En primer lugar, el segundo esperará menos de 5 milis si el bloqueo se lanza, porque no necesita esperar para despertarse del sleep. Por lo tanto, está menos expuesto al problema de inanición.

Después, j.u.c.l El paquete utiliza los métodos de parque Locksupport#para pausar un hilo, no Thread.sleep. Y según tengo entendido, hace diferencia en el planificador de hilos, el park permite una menor latencia, pero no estoy seguro de cómo exactamente el sleep está implementado.

Además, su código no tiene ningún sentido, se podría lograr exactamente el mismo efecto por lock() método.

Otros consejos

Está esperando el bloqueo y el hilo está dormido.

Internamente, si el tryLock(long, TimeUnit) El método no puede adquirir el bloqueo inmediatamente, espera la cantidad de tiempo especificado. Si el bloqueo está disponible antes de este tiempo, regresa inmediatamente con el bloqueo. Tenga en cuenta que en este caso, cuando hay múltiples hilos que solicitan un bloqueo, el ReentrantLock elegirá al azar un hilo para dar el bloqueo a la siguiente. Este comportamiento se puede cambiar pasando true al valor de equidad en el constructor new ReentrantLock(true).

El segundo ejemplo solo verificará el bloqueo cada cinco milisegundos. Si la cerradura está disponible mientras duerme y se entrega a otro hilo antes de que se despierte, este hilo no estará disponible para adquirir el bloqueo.

Si está utilizando este código con muchos hilos esperando el bloqueo, tenga en cuenta que ninguna solución que haya proporcionado garantizará que cada hilo obtendrá el bloqueo en algún momento. El segundo código puede continuar siendo cortado por otro hilo justo antes de que los cinco milisegundos estén arriba. El primer código es aleatorio, pero incluso con el valor de equidad establecido, cada hilo renunciará a su lugar en línea cada cinco milisegundos. Si este es el caso, es mejor que aumente el valor de tiempo de espera. Un buen valor sería aproximadamente el doble de la cantidad máxima de tiempo que esperaría que tome para cada hilo para obtener un giro.

Técnicamente no hay diferencia con respecto al estado del hilo de espera. Del Javadoc:

Si el bloqueo está sostenido por otro hilo, el hilo actual se deshabilita para fines de programación de hilos y se encuentra latente [...

Esto es muy similar a lo que sucede en caso de dormir, pero supongo que no podemos decir con certeza a menos que sepamos la implementación.

Ahora, tenga en cuenta esta parte:

...] yace latente hasta que sucede una de las tres cosas: el bloqueo es adquirido por el hilo actual; o [...

Eso significa que en caso de que el bloqueo se libere mientras tanto, lo adquirirá y regresará. En el otro caso, mientras duerme, el hilo no tiene la oportunidad de bloquear incluso si es gratis.

Otra diferencia sutil que puede aparecer entre los dos casos es el hecho de que la trylock cronometrada es sensible a la política de equidad del reentrante. Eso es:

Si este bloqueo se ha configurado para utilizar una política de pedido justo, no se adquirirá un bloqueo disponible si otros hilos esperan el bloqueo.

Se sabe que la trylock sin tiempo no es justa y puede tener éxito para adquirir el bloqueo incluso si otros hilos ya lo están esperando.

Supongo que el segundo esperará a que un 5 milisegundos obtenga la diferencia con el primero que intentará bloquearse de inmediato. Por lo tanto, el hilo B esperará si en 5 ms (dentro de 5 ms) bloqueará el bloqueo, no obtiene un bloqueo, devolverá falso. Normalmente no hay diferencia si tiene 5 ms en su tiempo de espera, pero en caso de que incrementa este número, obtendrá la imagen clara.

5ms es un tiempo de espera que esperará a 5 ms para un bloqueo, lo que significa que si el bloqueo está disponible después de los 3 ms, regresará después de 3 ms con verdadero.

Para obtener una gran referencia sobre cómo se implementan los bloqueos y otras primitivas de concurrencia, ver Shavit y Herlihy's Excelente El arte de la programación multiprocesador.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top