Respuestas:
Cuando usa bloqueos regulares (mutex, secciones críticas, etc.), el sistema operativo pone su hilo en el estado de ESPERA y se adelanta programando otros hilos en el mismo núcleo. Esto tiene una penalización de rendimiento si el tiempo de espera es realmente corto, porque su hilo ahora tiene que esperar una preferencia para recibir el tiempo de CPU nuevamente.
Además, los objetos del kernel no están disponibles en todos los estados del kernel, como en un controlador de interrupciones o cuando la paginación no está disponible, etc.
Los Spinlocks no causan preferencia, sino que esperan en un bucle ("giro") hasta que el otro núcleo libere el bloqueo. Esto evita que el hilo pierda su cuanto y continúe tan pronto como se libere el bloqueo. El simple mecanismo de spinlocks permite que un kernel lo utilice en casi cualquier estado.
Es por eso que en una máquina de un solo núcleo, un spinlock es simplemente una "desactivación de interrupciones" o "aumento de IRQL" que evita la programación de subprocesos por completo.
Los Spinlocks finalmente permiten que los kernels eviten los "Big Kernel Lock" (un bloqueo adquirido cuando el núcleo ingresa al kernel y se libera al salir) y tienen un bloqueo granular sobre las primitivas del kernel, lo que produce un mejor multiprocesamiento en máquinas de múltiples núcleos y, por lo tanto, un mejor rendimiento.
EDITAR : Surgió una pregunta: "¿Eso significa que debería usar spinlocks siempre que sea posible?" e intentaré responderla:
Como mencioné, los Spinlocks solo son útiles en lugares donde el tiempo de espera anticipado es más corto que un cuanto (lea: milisegundos) y la preferencia no tiene mucho sentido (por ejemplo, los objetos del kernel no están disponibles).
Si se desconoce el tiempo de espera o si está en modo de usuario, los Spinlocks no son eficientes. Consume el 100% del tiempo de CPU en el núcleo en espera mientras verifica si hay un bloqueo de giro disponible. Evita que otros subprocesos se ejecuten en ese núcleo hasta que expire su cuanto. Este escenario solo es factible para ráfagas cortas a nivel de kernel y es poco probable que sea una opción para una aplicación en modo de usuario.
Aquí hay una pregunta sobre SO que aborda eso: Spinlocks, ¿qué tan útiles son?
Supongamos que un recurso está protegido por un bloqueo, un hilo que desea acceder al recurso necesita adquirir el bloqueo primero. Si el bloqueo no está disponible, el subproceso puede comprobar repetidamente si se ha liberado el bloqueo. Durante este tiempo, el subproceso ocupado espera, verificando el bloqueo, usando la CPU, pero sin realizar ningún trabajo útil. Dicho bloqueo se denomina bloqueo de giro.
Es pertty mucho un bucle que continúa hasta que se cumple una determinada condición:
while(cantGoOn) {};
sleep(0)
, se adelantaría al hilo, eliminando el propósito de usar un spinlock en primer lugar. si necesita ceder a otros hilos, debe usar un candado regular. (Sé que su comentario es muy antiguo, pero quería evitar que otros lo vieran como una sugerencia).
while(something != TRUE ){};
// it happend
move_on();
Es un tipo de cerradura que está ocupada esperando
Se considera un anti-patrón, excepto para la programación del controlador de muy bajo nivel (donde puede suceder que llamar a una función de espera "adecuada" tenga más sobrecarga que simplemente bloquear por ocupado durante unos pocos ciclos).
Consulte, por ejemplo, Spinlocks en el kernel de Linux .
SpinLocks son aquellos en los que el hilo espera hasta que el bloqueo esté disponible. Esto normalmente se usará para evitar la sobrecarga de obtener los objetos del núcleo cuando existe la posibilidad de adquirir el objeto del núcleo dentro de un período de tiempo reducido.
Ex:
While(SpinCount-- && Kernel Object is not free)
{}
try acquiring Kernel object
Debería utilizar un bloqueo giratorio cuando crea que es más barato entrar en un bucle de espera ocupado y agrupar un recurso en lugar de bloquearlo cuando el recurso está bloqueado.
El giro puede ser beneficioso cuando los bloqueos son finos y numerosos (por ejemplo, un bloqueo por nodo en una lista vinculada), así como cuando los tiempos de retención de bloqueos son siempre extremadamente cortos. En general, mientras mantiene un bloqueo de giro, se debe evitar el bloqueo, llamar a cualquier cosa que pueda bloquear, mantener más de un bloqueo de giro a la vez, realizar llamadas enviadas dinámicamente (interfaz y virtuales), realizar llamadas enviadas estáticamente en cualquier código que no se tenga. t poseer o asignar memoria.
También es importante tener en cuenta que SpinLock es un tipo de valor, por razones de rendimiento. Como tal, uno debe tener mucho cuidado de no copiar accidentalmente una instancia de SpinLock, ya que las dos instancias (el original y la copia) serían completamente independientes entre sí, lo que probablemente conduciría a un comportamiento erróneo de la aplicación. Si se debe pasar una instancia de SpinLock, se debe pasar por referencia en lugar de por valor.
En pocas palabras, spinlock emplea instrucciones de comparación e intercambio atómico (CAS) o de prueba y configuración para implementar un lenguaje seguro para subprocesos sin bloqueo y sin espera. Estas estructuras se escalan bien en máquinas de varios núcleos.
Bueno, sí, el punto de los bloqueos de giro (frente a las secciones críticas tradicionales, etc.) es que ofrecen un mejor rendimiento en algunas circunstancias (sistemas multinúcleo ...), porque no producen inmediatamente el resto del cuanto del hilo.
Spinlock, es un tipo de bloqueo, que no se puede bloquear ni dormir. Cualquier hilo que desee adquirir un bloqueo de giro para cualquier recurso compartido o crítico girará continuamente, desperdiciando el ciclo de procesamiento de la CPU hasta que adquiera el bloqueo del recurso especificado. Una vez que se adquiere el spinlock, intenta completar el trabajo en su cuanto y luego libera el recurso respectivamente. Spinlock es el tipo de bloqueo de mayor prioridad, simplemente puedo decir, es un tipo de bloqueo no preventivo.