c - example - pthread_mutex_init
¿Cuándo es pthread_spin_lock lo correcto para usar(por ejemplo, un pthread mutex)? (4)
El método más seguro con un aumento de rendimiento es un híbrido de los dos: un mutex adaptativo.
Cuando su sistema tiene múltiples núcleos, gira durante algunos miles de ciclos para capturar el mejor caso de baja o nula contención, luego difiera a un mutex completo para ceder a otros hilos para bloqueos largos disputados.
Tanto POSIX ( PTHREAD_MUTEX_ADAPTIVE_NP
) como Win32 ( SetCriticalSectionSpinCount
) tienen mutexes adaptativos, muchas plataformas no tienen una API POSIX spinlock.
Dado que pthread_spin_lock está disponible, ¿cuándo lo usaría y cuándo no debería usarlo?
es decir, ¿cómo decidiría proteger alguna estructura de datos compartida con un pthread mutex o un pthread spinlock?
El spinlock es un bloqueo de "espera ocupada". Su principal ventaja es que mantiene la secuencia activa y no provocará un cambio de contexto, por lo que si sabe que solo estará esperando por un tiempo muy corto (porque su operación crítica es muy rápida), entonces esto puede brindarle un mejor rendimiento. que un mutex Por el contrario, un mutex causará menos demanda en el sistema si la sección crítica lleva mucho tiempo y se desea un cambio de contexto.
TL; DR: depende.
La respuesta corta es que un spinlock puede ser mejor cuando planea mantener el bloqueo durante un intervalo extremadamente corto (por ejemplo, para hacer nada más que incrementar un contador), y se espera que la contención sea rara, pero la operación ocurre con la frecuencia suficiente para ser un posible cuello de botella de rendimiento. Las ventajas de un spinlock sobre un mutex son:
- Al desbloquear, no es necesario verificar si otros hilos pueden estar esperando el bloqueo y activándolo. Desbloquear es simplemente una sola instrucción de escritura atómica.
- Si no se obtiene inmediatamente el bloqueo, no se pone a dormir el hilo, por lo que es posible que pueda obtener el bloqueo con una latencia mucho más baja tan pronto como esté disponible.
- No hay riesgo de que la contaminación de la memoria caché ingrese al espacio del kernel para dormir o despertar otros hilos.
El punto 1 siempre permanecerá, pero los puntos 2 y 3 tienen una utilidad algo disminuida si se considera que las buenas implementaciones mutex probablemente girarán un número de veces decente antes de pedir ayuda al kernel.
Ahora, la respuesta larga:
Lo que debe preguntarse antes de utilizar spinlocks es si estas ventajas potenciales superan una desventaja rara pero muy real: qué sucede cuando el programador detiene la interrupción del bloqueo antes de que pueda liberar el bloqueo. Por supuesto, esto es raro, pero puede suceder incluso si el bloqueo solo se mantiene para una única operación de incremento variable o algo igualmente igualmente trivial. En este caso, cualquier otro subproceso que intente obtener el bloqueo seguirá girando hasta que el hilo que contiene el bloqueo se programe y tenga la oportunidad de liberar el bloqueo. Esto nunca puede suceder si los subprocesos que intentan obtener el bloqueo tienen mayores prioridades que el subproceso que contiene el bloqueo. Ese puede ser un caso extremo, pero incluso sin prioridades diferentes en juego, puede haber demoras muy largas antes de que el propietario del bloqueo se programe nuevamente, y lo peor de todo, una vez que esta situación comience, puede escalar rápidamente tantos hilos, todos con la esperanza de obtener el bloqueo, comenzar a girar sobre él, inmovilizar más tiempo de procesador y retrasar aún más la programación del hilo que podría liberar el bloqueo.
Como tal, tendría cuidado con los espirales ... :-)
Spinlock solo tiene interés en el contexto MP. Se usa para ejecutar tareas pseudoatómicas. En el sistema monoprocesador, el principio es el siguiente:
- Bloquee el programador (si la tarea se ocupa de las interrupciones, bloquee las interrupciones en su lugar)
- Hacer mi táctica atómica
- Desbloquee el programador
Pero en los sistemas MP no tenemos garantías de que otro núcleo no ejecute otro hilo que pueda entrar en nuestra sección de códigos. Para evitar esto, se ha creado el bloqueo de giro, su objetivo es posponer la ejecución de otros núcleos que evitan el problema de concurrencia. La sección crítica se convierte en:
- Bloquear el programador
- SpinLock (evita la entrada de otros núcleos)
- Mi tarea
- SpinUnlock
- Desbloqueo de tareas
Si se omite el bloqueo de la tarea, durante una programación, otro subproceso podría tratar de ingresar a la sección y se repetirá al 100% de la CPU esperando la siguiente programación. Si esta tarea es de alta prioridad, producirá un interbloqueo.