un spinlock es un bloqueo que hace que un hilo que intenta adquirirlo simplemente espere en un bucle ("giro") mientras verifica repetidamente si el bloqueo está disponible
Esto suena muy parecido a:
while(!ready);
Me enseñaron a evitar las encuestas siempre que sea posible, ya que era completamente subóptimo. Entonces, ¿es spinlock un nombre elegante para las encuestas antiguas? ¿En qué se diferencia un spinlock del sondeo?
El sondeo se refiere a verificar repetidamente si un recurso ( cualquier tipo de recurso) está listo.
Un spinlock es cuando el recurso que está sondeando es un candado.
Tenga en cuenta que las encuestas no son malas. En particular, el sondeo es eficiente cuando generalmente hay datos listos cuando sondea. El sondeo solo es ineficiente si lo hace sin obtener datos a cambio.
Por otro lado, las interrupciones son ineficientes si hay tantos datos que constantemente te interrumpen. Son eficientes si los datos llegan lo suficientemente raramente como para que pueda realizar un trabajo útil antes de ser interrumpido.
Puedo darle un ejemplo de la vida real desde mi propia experiencia: hace 15 años, tenía mi programa de correo electrónico configurado para interrumpirme cada vez que recibía un nuevo correo electrónico. Lo que ocurría una o dos veces por semana. Comprobar constantemente mi bandeja de entrada habría sido una pérdida de tiempo colosal.
Hoy en día, tengo todas las notificaciones desactivadas. Yo sé que cada vez que miro en mi bandeja de entrada, no habrá nuevos correos electrónicos allí. El sondeo es mucho más eficiente ahora.
Los Spinlocks son eficientes cuando a) la probabilidad de que se tome el bloqueo es baja, yb) si se toma el bloqueo, solo se mantendrá por un corto tiempo. En otras palabras: es eficiente para cerraduras de grano fino en su mayoría no contenidas, pero ineficiente para cerraduras de grano grueso altamente contenidas.
(Y, por supuesto, los spinlocks solo funcionan cuando hay un verdadero paralelismo, de lo contrario, el otro hilo no tendrá la oportunidad de liberar el bloqueo. Supongo que es algo obvio, pero quería decirlo de todos modos).
@ Kevin: Tengo una idea muy purista de un spinlock, literalmente un candado que simplemente gira en un bucle vacío. ( atomically_do { while (lock.is_locked?); lock.acquire! }) Si cede, no es un bucle vacío y, por lo tanto, no es un spinlock en esa visión purista :-D Pero, por supuesto, cierta hibridación con otros tipos de bloqueos o relajaciones / adiciones al ideal platónico tiene mucho sentido en el mundo real.
Jörg W Mittag
3
@bubakazouba: Un spinlock funciona literalmente "girando" en un bucle vacío y marcando "¿Ya se ha desbloqueado el bloqueo? ¿Ya se ha desbloqueado el bloqueo? ¿Ya se ha desbloqueado el bloqueo? ¿Ya se ha desbloqueado el bloqueo?" una y otra vez. Si no hay paralelismo, entonces no hay otro hilo ejecutándose al mismo tiempo que pueda liberar el bloqueo, ¡así que efectivamente tienes un bucle sin fin! Vea el comentario directamente encima del suyo.
Jörg W Mittag el
1
@kasperd: aún puede ver la multitarea cooperativa en software de servidor controlado por eventos como nginx. En ese caso, hay un hilo y no hay bloqueo, lo que significa que solo puede explotar un núcleo. Que yo sepa, literalmente no hay ejemplos del mundo real de la verdadera multitarea cooperativa multinúcleo. Tal sistema sería estúpido, ya que obtendría todas las desventajas de la multitarea cooperativa sin la ventaja de no tener bloqueos.
Kevin
10
Un spinlock es un tipo de bloqueo, específicamente, uno logrado mediante sondeo.
El sondeo es un método para verificar el estado de algo (al preguntar por el estado, en lugar de esperar a que se le informe).
No todas las encuestas son un spinlock, por ejemplo, sondear el estado de las teclas del teclado.
Además, las encuestas no son inherentemente malas. Períodos muy cortos de sondeo pueden evitar costosos cambios de contexto que requeriría el uso de interrupciones, sin mencionar que el sondeo a veces puede ser más simple de implementar y, por lo tanto, más fácil de mantener, especialmente en niveles más bajos. Como de costumbre, los absolutos son una cosa terrible, y debe usar el método que proporciona el rendimiento / complejidad apropiado para sus necesidades tal como las ha medido , en lugar de usar o descartar opciones a ciegas.
Spinlock es diferente del sondeo porque solo ocurre durante un período de tiempo muy corto, del orden de unos pocos milisegundos o menos. El sondeo puede continuar indefinidamente.
En la programación paralela, un breve episodio de giro a menudo es preferible al bloqueo, ya que evita el costo del cambio de contexto y las transiciones del núcleo.
Creo que querías decir microsegundos. Para un bloqueo que dura un milisegundo completo, deberíamos usar una implementación de bloqueo que haga una llamada al núcleo en la contienda.
Peter
@Peter Quizás eso es lo que Albahari quiso decir. Eso es lo que dice su texto.
Robert Harvey
4
La diferencia es que un spinlock se usa (con suerte) solo en situaciones donde es apropiado, y en estas situaciones es muy eficiente.
Utiliza un spinlock si espera que un recurso solo se bloquee por un tiempo muy corto, por ejemplo, si un bloqueo solo se usa para actualizar una variable. El spinlock sondea la cerradura a la velocidad máxima, pero con suerte por menos de microsegundos. Un mutex normal requeriría en la llamada del sistema operativo. SI el bloqueo solo se mantiene durante una pequeña cantidad de tiempo, entonces el spinlock solo usa una pequeña cantidad de tiempo de CPU, mientras que la llamada del sistema operativo tomará más tiempo. Pero si esta expectativa es incorrecta, entonces el spinlock es muy ineficiente: usará el 100% del tiempo de CPU en una CPU, mientras que el mutex normal solo toma el tiempo para ingresar al sistema operativo y regresar.
A veces ambos se combinan; ejecuta el bloqueo de giro durante un breve período de tiempo y cambia a una estrategia diferente si el bloqueo de giro no funciona.
El sondeo excesivo es algo que no debe hacer porque desperdicia recursos del sistema. Se deduce que el sondeo está bien si no desperdicia recursos del sistema .
Por ejemplo, un sondeo excesivo elevará la carga de la CPU al 100% en los casos en que el trabajo real solo resulte en una carga del 2%.
El sondeo se puede usar para otras cosas que no sean while(!ready). Por ejemplo, significa verificar regularmente si el usuario presionó una tecla. Una implementación sensata comprobará como máximo una vez cada 15 milisegundos, por lo que es una comprobación cada ~ 20 millones de ciclos de reloj. Ese tipo de encuestas es excelente, porque no desperdicia recursos del sistema.
Un SpinLock no es un caso especial. Si tenemos un SpinLock y un hilo ingresa al bloqueo, y otro tiene que esperar, el SpinLock es la elección incorrecta si y solo si el hilo en espera desperdicia recursos del sistema. El subproceso en espera desperdiciará recursos del sistema si y solo si tiene que esperar una cantidad significativa de tiempo antes de que pueda adquirir el bloqueo.
Por lo tanto, usar un SpinLock para proteger cualquier cosa que requiera un par de miles de ciclos de reloj o más antes de que se desbloquee nuevamente (por ejemplo, compilar y ejecutar una pieza de JavaScript sobre la marcha) es malo, exactamente por la razón que usted indicó. Pero usar un SpinLock para proteger algo que se completa rápidamente, como acceder a un mapa hash implementado correctamente, está bien porque el hilo de espera solo girará 2 o 3 veces y, por lo tanto, no desperdicia recursos del sistema.
atomically_do { while (lock.is_locked?); lock.acquire! }
) Si cede, no es un bucle vacío y, por lo tanto, no es un spinlock en esa visión purista :-D Pero, por supuesto, cierta hibridación con otros tipos de bloqueos o relajaciones / adiciones al ideal platónico tiene mucho sentido en el mundo real.Un spinlock es un tipo de bloqueo, específicamente, uno logrado mediante sondeo.
El sondeo es un método para verificar el estado de algo (al preguntar por el estado, en lugar de esperar a que se le informe).
No todas las encuestas son un spinlock, por ejemplo, sondear el estado de las teclas del teclado.
Además, las encuestas no son inherentemente malas. Períodos muy cortos de sondeo pueden evitar costosos cambios de contexto que requeriría el uso de interrupciones, sin mencionar que el sondeo a veces puede ser más simple de implementar y, por lo tanto, más fácil de mantener, especialmente en niveles más bajos. Como de costumbre, los absolutos son una cosa terrible, y debe usar el método que proporciona el rendimiento / complejidad apropiado para sus necesidades tal como las ha medido , en lugar de usar o descartar opciones a ciegas.
fuente
Spinlock es diferente del sondeo porque solo ocurre durante un período de tiempo muy corto, del orden de unos pocos milisegundos o menos. El sondeo puede continuar indefinidamente.
En la programación paralela, un breve episodio de giro a menudo es preferible al bloqueo, ya que evita el costo del cambio de contexto y las transiciones del núcleo.
Lecturas adicionales
SpinLock y SpinWait en C #
Spinlocks y Read-Write Locks en C
fuente
La diferencia es que un spinlock se usa (con suerte) solo en situaciones donde es apropiado, y en estas situaciones es muy eficiente.
Utiliza un spinlock si espera que un recurso solo se bloquee por un tiempo muy corto, por ejemplo, si un bloqueo solo se usa para actualizar una variable. El spinlock sondea la cerradura a la velocidad máxima, pero con suerte por menos de microsegundos. Un mutex normal requeriría en la llamada del sistema operativo. SI el bloqueo solo se mantiene durante una pequeña cantidad de tiempo, entonces el spinlock solo usa una pequeña cantidad de tiempo de CPU, mientras que la llamada del sistema operativo tomará más tiempo. Pero si esta expectativa es incorrecta, entonces el spinlock es muy ineficiente: usará el 100% del tiempo de CPU en una CPU, mientras que el mutex normal solo toma el tiempo para ingresar al sistema operativo y regresar.
A veces ambos se combinan; ejecuta el bloqueo de giro durante un breve período de tiempo y cambia a una estrategia diferente si el bloqueo de giro no funciona.
fuente
El sondeo excesivo es algo que no debe hacer porque desperdicia recursos del sistema. Se deduce que el sondeo está bien si no desperdicia recursos del sistema .
Por ejemplo, un sondeo excesivo elevará la carga de la CPU al 100% en los casos en que el trabajo real solo resulte en una carga del 2%.
El sondeo se puede usar para otras cosas que no sean
while(!ready)
. Por ejemplo, significa verificar regularmente si el usuario presionó una tecla. Una implementación sensata comprobará como máximo una vez cada 15 milisegundos, por lo que es una comprobación cada ~ 20 millones de ciclos de reloj. Ese tipo de encuestas es excelente, porque no desperdicia recursos del sistema.Un SpinLock no es un caso especial. Si tenemos un SpinLock y un hilo ingresa al bloqueo, y otro tiene que esperar, el SpinLock es la elección incorrecta si y solo si el hilo en espera desperdicia recursos del sistema. El subproceso en espera desperdiciará recursos del sistema si y solo si tiene que esperar una cantidad significativa de tiempo antes de que pueda adquirir el bloqueo.
Por lo tanto, usar un SpinLock para proteger cualquier cosa que requiera un par de miles de ciclos de reloj o más antes de que se desbloquee nuevamente (por ejemplo, compilar y ejecutar una pieza de JavaScript sobre la marcha) es malo, exactamente por la razón que usted indicó. Pero usar un SpinLock para proteger algo que se completa rápidamente, como acceder a un mapa hash implementado correctamente, está bien porque el hilo de espera solo girará 2 o 3 veces y, por lo tanto, no desperdicia recursos del sistema.
fuente