GNU/Linux >> Tutoriales Linux >  >> Linux

Spinlock frente a semáforo

Spinlock y semáforo difieren principalmente en cuatro cosas:

1. Que son
Un bloqueo giratorio es una posible implementación de un bloqueo, es decir, una que se implementa mediante la espera ocupada ("girando"). Un semáforo es una generalización de un candado (o, al revés, un candado es un caso especial de un semáforo). Por lo general, pero no necesariamente , los spinlocks solo son válidos dentro de un proceso, mientras que los semáforos también se pueden usar para sincronizar entre diferentes procesos.

Un candado funciona por exclusión mutua, eso es uno hilo a la vez puede adquirir el bloqueo y continuar con una "sección crítica" del código. Por lo general, esto significa código que modifica algunos datos compartidos por varios subprocesos.
Un semáforo tiene contador y se dejará adquirir por uno o varios subprocesos, según el valor que publique en él y (en algunas implementaciones) según cuál sea su valor máximo permitido.

En la medida en que se puede considerar un bloqueo como un caso especial de un semáforo con un valor máximo de 1.

2. Qué hacen
Como se indicó anteriormente, un spinlock es un bloqueo y, por lo tanto, un mecanismo de exclusión mutua (estrictamente 1 a 1). Funciona consultando y/o modificando repetidamente una ubicación de memoria, generalmente de manera atómica. Esto significa que adquirir un spinlock es una operación "ocupada" que posiblemente consuma ciclos de CPU durante mucho tiempo (¡quizás para siempre!) mientras que efectivamente no logra "nada".
El principal incentivo para este enfoque es el hecho de que un cambio de contexto tiene una sobrecarga equivalente a girar unos cientos (o tal vez miles) de veces, por lo que si se puede adquirir un bloqueo quemando unos pocos ciclos girando, esto en general puede ser muy bien más eficiente. Además, para las aplicaciones en tiempo real, puede que no sea aceptable bloquear y esperar a que el programador vuelva a ellas en algún momento lejano en el futuro.

Un semáforo, por el contrario, no gira en absoluto o solo gira durante un tiempo muy corto (como una optimización para evitar la sobrecarga de llamada al sistema). Si no se puede adquirir un semáforo, se bloquea, cediendo tiempo de CPU a un subproceso diferente que está listo para ejecutarse. Por supuesto, esto puede significar que pasan unos pocos milisegundos antes de que su subproceso se programe nuevamente, pero si esto no es un problema (generalmente no lo es), entonces puede ser un enfoque muy eficiente que conserva la CPU.

3. Cómo se comportan en presencia de congestión
Es un error común pensar que los spinlocks o los algoritmos sin bloqueo son "generalmente más rápidos" o que solo son útiles para "tareas muy cortas" (idealmente, ningún objeto de sincronización debe mantenerse más tiempo del absolutamente necesario).
La única diferencia importante es cómo se comportan los diferentes enfoques en presencia de congestión .

Un sistema bien diseñado normalmente tiene poca o ninguna congestión (esto significa que no todos los subprocesos intentan adquirir el bloqueo al mismo tiempo). Por ejemplo, uno normalmente no escriba un código que adquiera un bloqueo, luego cargue medio megabyte de datos comprimidos en zip desde la red, decodifique y analice los datos, y finalmente modifique una referencia compartida (agregar datos a un contenedor, etc.) antes de liberar el bloqueo. En cambio, uno adquiriría el bloqueo solo con el fin de acceder al recurso compartido .
Dado que esto significa que hay considerablemente más trabajo fuera de la sección crítica que dentro de ella, naturalmente, la probabilidad de que un subproceso esté dentro de la sección crítica es relativamente baja y, por lo tanto, pocos subprocesos compiten por el bloqueo al mismo tiempo. Por supuesto, de vez en cuando, dos subprocesos intentarán adquirir el bloqueo al mismo tiempo (si esto no pudo suceda que no necesitaría un candado!), pero esto es más bien la excepción que la regla en un sistema "saludable".

En tal caso, un spinlock muy supera a un semáforo porque si no hay congestión de bloqueo, la sobrecarga de adquirir el spinlock es de una docena de ciclos en comparación con cientos/miles de ciclos para un cambio de contexto o 10-20 millones de ciclos para perder el resto de un segmento de tiempo.

Por otro lado, dada la alta congestión, o si el bloqueo se mantiene durante períodos prolongados (¡a veces simplemente no puede evitarlo!), un spinlock quemará cantidades increíbles de ciclos de CPU sin lograr nada.
Un semáforo (o exclusión mutua) es una opción mucho mejor en este caso, ya que permite que un subproceso diferente se ejecute útil tareas durante ese tiempo. O, si ningún otro subproceso tiene algo útil que hacer, permite que el sistema operativo acelere la CPU y reduzca el calor/conserve energía.

Además, en un sistema de un solo núcleo, un spinlock será bastante ineficiente en presencia de congestión de bloqueo, ya que un subproceso giratorio perderá todo su tiempo esperando un cambio de estado que posiblemente no suceda (no hasta que se programe el lanzamiento del subproceso, que no está pasando mientras el subproceso en espera se está ejecutando!). Por lo tanto, dada cualquier cantidad de contención, adquirir el bloqueo toma alrededor de 1 1/2 intervalos de tiempo en el mejor de los casos (suponiendo que el hilo de liberación es el siguiente que se programa), lo cual no es un comportamiento muy bueno.

4. Cómo se implementan
Actualmente, un semáforo generalmente envuelve sys_futex bajo Linux (opcionalmente con un spinlock que sale después de algunos intentos).
Un spinlock generalmente se implementa mediante operaciones atómicas y sin usar nada proporcionado por el sistema operativo. En el pasado, esto significaba usar intrínsecos del compilador o instrucciones de ensamblador no portátiles. Mientras tanto, tanto C ++ 11 como C11 tienen operaciones atómicas como parte del lenguaje, por lo que, aparte de la dificultad general de escribir un código sin bloqueo comprobablemente correcto, ahora es posible implementar código sin bloqueo en un formato completamente portátil y (casi) forma indolora.


Más allá de lo que dijeron Yoav Aviram y gbjbaanb, el otro punto clave solía ser que nunca usaría un bloqueo de giro en una máquina de una sola CPU, mientras que un semáforo tendría sentido en una máquina de este tipo. Hoy en día, con frecuencia es difícil encontrar una máquina sin múltiples núcleos, hiperprocesamiento o equivalente, pero en las circunstancias en las que solo tiene una CPU, debe usar semáforos. (Confío en que la razón sea obvia. Si la única CPU está ocupada esperando que otra cosa libere el bloqueo giratorio, pero se está ejecutando en la única CPU, es poco probable que se libere el bloqueo hasta que el proceso o subproceso actual sea reemplazado por el sistema operativo, lo que puede llevar un tiempo y no sucede nada útil hasta que se produce la preferencia).


muy simple, un semáforo es un objeto de sincronización "que rinde", un spinlock es uno de "espera ocupada". (Hay un poco más de semáforos en el sentido de que sincronizan varios subprocesos, a diferencia de un mutex o guardia o monitor o sección crítica que protege una región de código de un solo subproceso)

Usaría un semáforo en más circunstancias, pero use un spinlock donde se bloqueará por un tiempo muy corto; el bloqueo tiene un costo, especialmente si bloquea mucho. En tales casos, puede ser más eficiente hacer spinlock durante un tiempo a la espera de que se desbloquee el recurso protegido. Obviamente, hay un impacto en el rendimiento si giras durante demasiado tiempo.

por lo general, si gira durante más tiempo que un hilo cuántico, entonces debe usar un semáforo.


Linux
  1. Ubuntu - Linux - ¿Tiempo de cambio de archivo versus tiempo de modificación?

  2. ¿Cómo matar el proceso que mantiene el bloqueo Apt?

  3. ¿Cómo configurar el tiempo de pantalla de bloqueo personalizado en Ubuntu 18.04?

  4. Estados de proceso de Linux

  5. Forzar una activación espuria en Java

Comando de tiempo de Linux

Último comando en Linux

Programación con cron &At

Hora del sistema

¿El indicador de hora no muestra la fecha/hora?

Cambiar hora temporalmente