Pregunta

Durante la lectura de C # 3.0 en una cáscara de nuez por Joseph y Ben Albahari , me encontré con el siguiente párrafo (página 673, párrafo primero, en sección titulada " señalización con Esperar y pulso ")

  

"La monitor clase proporciona otra construcción de señalización a través de dos métodos estáticos, Espera y pulso . El principio es que podemos escribir la lógica de señalización usted mismo usando banderas y campos personalizados (encerrado en bloqueo declaraciones), y luego introducir Espera y pulso comandos a hilar CPU mitigar. La ventaja de este enfoque de bajo nivel es que con sólo Espera , pulso y bloqueo declaración, se puede lograr la funcionalidad de AutoResetEvent , ManualResetEvent y semáforo , así como WaitHandle 's métodos estáticos WaitAll y WaitAny . Por otra parte, Espera y pulso   pueden ser susceptibles en situaciones en las   todos los mangos son de espera   parsimonia desafiado ".

Mi pregunta es, ¿cuál es la interpretación correcta de la última frase?

  • Una situación con un gran número decente / de las manijas de espera donde WaitOne () sólo se le llama de vez en cuando en cualquier mango de espera en particular.
  • Una situación con un gran número decente / de las manijas de espera, donde rara vez lo hace más de un hilo tienden a bloquear en cualquier mango de espera en particular.
  • Algunos otra interpretación.

Le agradeceremos que iluminan ejemplos de este tipo de situaciones y quizás la forma y / o por la que se manejan de manera más eficiente a través de espera y el pulso más que por otros métodos.

Gracias!

Edit: He encontrado el texto online aquí

¿Fue útil?

Solución

Lo que esto quiere decir es que hay algunas situaciones en las Esperar y pulso proporciona una solución más simple que las manijas de espera. En general, esto ocurre cuando:

  • El camarero, en lugar de al notificador, decide cuándo Desbloquear
  • La condición de bloqueo implica algo más que una simple bandera (quizás varias variables)

Puede seguir utilizando las manijas de espera en estas situaciones, pero Espera / pulso tiende a ser más simple. Lo bueno de Espera / pulso es que esperan libera el bloqueo subyacente a la espera. Por ejemplo, en el siguiente ejemplo, estamos _x e _y la lectura dentro de la seguridad de una cerradura - y sin embargo, que el bloqueo se libera a la espera para que otro hilo puede actualizar esas variables:

lock (_locker)
{
  while (_x < 10 && _y < 20) Monitor.Wait (_locker);
}

Otro hilo puede entonces actualizar _x y _y atómicamente (en virtud de la cerradura) y después del pulso para señalar el camarero:

lock (_locker)
{
  _x = 20;
  _y = 30;
  Monitor.Pulse (_locker);
} 

La desventaja de Espera / Pulso es que es más fácil de hacerlo mal y cometer un error (por ejemplo, mediante la actualización de una variable y olvidarse de pulso). En situaciones en las que un programa con asas espera es igualmente simple a un programa con Espera / Pulso, recomiendo ir con asas de espera por esa razón.

En términos de consumo / eficiencia de recursos (que creo que estaba aludiendo a), Espera / pulso es generalmente más rápido y más ligero (ya que tiene una aplicación administrada). Esto no suele ser un gran problema en la práctica, sin embargo. Y en ese momento, Framework 4.0 incluye versiones de baja sobrecarga que gestiona de ManualResetEvent y semáforo (ManualResetEventSlim y SemaphoreSlim).

Framework 4.0 también ofrece muchas más opciones de sincronización que disminuye la necesidad de Espera / Pulso:

  • CountdownEvent
  • Barrera
  • PLINQ / Paralelismo de datos (AsParallel, Parallel.Invoke, Parallel.For, Parallel.ForEach)
  • Tareas y continuaciones

Todos éstos son mucho más altos niveles de esperar / pulso y la OMI son preferibles para escribir código fiable y fácil de mantener (suponiendo que va a resolver la tarea en cuestión).

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