multithreading - thread - ¿Qué es la contención de hilos?
que son los hilos en programacion (10)
Imagine el siguiente escenario. Te estás preparando para el examen final de mañana y te sientes un poco hambriento. Entonces, le das diez dólares a tu hermano menor y le pides que te compre una pizza. En este caso, usted es el hilo principal y su hermano es un hilo secundario. Una vez que se da su orden, tanto usted como su hermano están haciendo su trabajo al mismo tiempo (es decir, estudiando y comprando una pizza). Ahora, tenemos dos casos para considerar. Primero, tu hermano te devuelve la pizza y termina mientras estudias. En este caso, puedes dejar de estudiar y disfrutar de la pizza. En segundo lugar, terminas tu estudio temprano y duermes (es decir, tu trabajo asignado para hoy - estudiar para el examen final de mañana - está listo) antes de que la pizza esté disponible. Por supuesto, no puedes dormir; de lo contrario, no tendrás la oportunidad de comer la pizza. Lo que vas a hacer es esperar hasta que tu hermano te devuelva la pizza.
Como en el ejemplo, los dos casos dan sentido a la rivalidad.
¿Puede alguien explicar por favor qué es la contención del hilo?
Lo busqué en Google, pero no puedo encontrar una explicación simple.
La contención de bloqueo tiene lugar cuando un hilo intenta adquirir el bloqueo de un objeto que ya ha sido adquirido por otro hilo *. Hasta que se libere el objeto, el hilo está bloqueado (en otras palabras, está en estado de Espera). En algunos casos, esto puede conducir a una llamada ejecución en serie que afecta negativamente a la aplicación.
Básicamente, la contención de hilos es una condición en la que un hilo está esperando un bloqueo / objeto que está siendo retenido por otro hilo. Por lo tanto, este hilo de espera no puede usar ese objeto hasta que el otro hilo haya desbloqueado ese objeto en particular.
Creo que debería haber alguna aclaración del PO sobre el trasfondo de la pregunta: puedo pensar en 2 respuestas (aunque estoy seguro de que hay adiciones a esta lista):
si se refiere al "concepto" general de contención de hilos y cómo se puede presentar en una aplicación, difiero a la respuesta detallada de @DavidSchwartz anterior.
También está el contador de rendimiento ''.NET CLR Locks and Threads: Total # of Contentions''. Según se desprende de la descripción de PerfMon para este contador, se define como:
Este contador muestra la cantidad total de veces que los hilos en el CLR han intentado adquirir un bloqueo administrado sin éxito. Los bloqueos administrados se pueden adquirir de muchas maneras; por la instrucción "lock" en C # o llamando a System.Monitor.Enter o usando MethodImplOptions. Atributo personalizado sincronizado.
... y estoy seguro de que otros para otros sistemas operativos y marcos de aplicaciones.
Desde here :
Una disputa ocurre cuando un hilo está esperando un recurso que no está disponible; ralentiza la ejecución de su código, pero puede desaparecer con el tiempo.
Se produce un interbloqueo cuando un subproceso está esperando un recurso que un segundo subproceso ha bloqueado, y el segundo subproceso está esperando un recurso que el primer subproceso ha bloqueado. Más de dos hilos pueden estar involucrados en un punto muerto. Un punto muerto nunca se resuelve solo. A menudo provoca la detención de toda la aplicación, o la parte que está experimentando el punto muerto.
La contención de subprocesos también se ve afectada por las operaciones de E / S. Ejemplo cuando un hilo que espera la lectura del archivo puede considerarse una disputa. Use los puertos de terminación de E / S como solución.
Otra palabra podría ser concurrencia. Es simplemente la idea de que dos o más hilos intenten usar el mismo recurso.
Para mí, la contención es una competencia entre 2 o más hilos sobre un recurso compartido. El recurso puede ser un candado, un mostrador, etc. La competencia significa "quién la obtiene primero". Cuantos más hilos, más contención. Cuanto más frecuente es el acceso a un recurso, más contención.
Tienes 2 hilos. Subproceso A y Subproceso B, también tiene el objeto C.
A está accediendo al objeto C y ha colocado un bloqueo en ese objeto. B necesita acceder al objeto C, pero no puede hacerlo hasta que A libere el bloqueo en el objeto C.
Varias respuestas parecen enfocarse en la contención de bloqueos, pero los bloqueos no son los únicos recursos en los que se puede experimentar la contención. La contención es simplemente cuando dos hilos intentan acceder al mismo recurso o recursos relacionados de tal manera que al menos uno de los hilos contendientes se ejecuta más lentamente de lo que lo haría si el otro hilo (s) no se ejecuta.
El ejemplo más obvio de contención es en un candado. Si el hilo A tiene un bloqueo y el hilo B quiere adquirir el mismo bloqueo, el hilo B tendrá que esperar hasta que el hilo A libere el bloqueo.
Ahora, esto es específico de la plataforma, pero el hilo puede experimentar ralentizaciones incluso si nunca tiene que esperar a que el otro hilo libere el bloqueo. Esto se debe a que un bloqueo protege algún tipo de datos y, a menudo, también se contestarán los mismos datos.
Por ejemplo, considere un hilo que adquiera un bloqueo, modifique un objeto, luego libere el bloqueo y haga otras cosas. Si dos subprocesos hacen esto, incluso si nunca luchan por el bloqueo, los subprocesos pueden ejecutarse mucho más lentamente de lo que lo harían si solo se ejecutara un subproceso.
¿Por qué? Supongamos que cada subproceso se ejecuta en su propio núcleo en una CPU x86 moderna y los núcleos no comparten una memoria caché L2. Con solo un hilo, el objeto puede permanecer en el caché L2 la mayor parte del tiempo. Con ambos subprocesos en ejecución, cada vez que un subproceso modifica el objeto, el otro subproceso encontrará que los datos no están en su caché L2 porque la otra CPU invalidó la línea de caché. En un Pentium D, por ejemplo, esto hará que el código se ejecute a la velocidad del FSB, que es mucho menor que la velocidad de caché L2.
Como la contención puede ocurrir incluso si el bloqueo no se disputa por sí mismo, la contención también puede ocurrir cuando no hay un bloqueo. Por ejemplo, supongamos que su CPU admite un incremento atómico de una variable de 32 bits. Si un hilo sigue incrementando y disminuyendo una variable, la variable estará caliente en el caché la mayor parte del tiempo. Si dos subprocesos lo hacen, sus cach contienden por la propiedad de la memoria que contiene esa variable, y muchos accesos serán más lentos a medida que el protocolo de coherencia de caché opera para asegurar cada propiedad central de la línea de caché.
Irónicamente, los bloqueos típicamente reducen la contención. ¿Por qué? Porque sin un bloqueo, dos subprocesos podrían operar en el mismo objeto o colección y causar mucha contención (por ejemplo, hay colas sin bloqueo). Los bloqueos tenderán a desprogramar subprocesos contendientes, permitiendo que se ejecuten subprocesos no contendientes en su lugar. Si el hilo A contiene un bloqueo y el hilo B quiere el mismo bloqueo, la implementación puede ejecutar el hilo C en su lugar. Si el hilo C no necesita ese bloqueo, la contención futura entre los hilos A y B puede evitarse por un tiempo. (Por supuesto, esto supone que hay otros hilos que podrían ejecutarse. No ayudará si la única forma en que el sistema como un todo puede hacer un progreso útil es ejecutando hilos que contengan).