Cuándo debemos usar mutex y cuándo debemos usar semáforo


Respuestas:


92

Así es como recuerdo cuándo usar qué:

Semáforo: use un semáforo cuando (hilo) quiera dormir hasta que otro hilo le indique que se despierte. El semáforo 'abajo' ocurre en un hilo (productor) y el semáforo 'arriba' (para el mismo semáforo) ocurre en otro hilo (consumidor) por ejemplo: En un problema productor-consumidor, el productor quiere dormir hasta que al menos una ranura del búfer esté vacía, solo el hilo del consumidor puede saber cuándo una ranura de búfer está vacía.

Mutex: Use un mutex cuando (hilo) desee ejecutar código que no debería ser ejecutado por ningún otro hilo al mismo tiempo. Mutex 'down' ocurre en un hilo y mutex 'up' debe ocurrir en el mismo hilo más adelante. Por ejemplo: si está eliminando un nodo de una lista vinculada global, no desea que otro hilo se entretenga con punteros mientras elimina el nodo. Cuando adquiere un mutex y está ocupado eliminando un nodo, si otro hilo intenta adquirir el mismo mutex, se pondrá en suspensión hasta que libere el mutex.

Spinlock: Use un spinlock cuando realmente quiera usar un mutex pero su hilo no puede dormir. Por ejemplo: un controlador de interrupciones dentro del núcleo del sistema operativo nunca debe dormir. Si lo hace, el sistema se congelará / bloqueará. Si necesita insertar un nodo en la lista vinculada compartida globalmente desde el controlador de interrupciones, adquiera un spinlock - insert node - release spinlock.


1
agregar a: los semáforos y el mutex son dos formas de proporcionar sincronización. semáforo, puede estar más relacionado con la señalización (por ejemplo, escenario de problema de productor y consumidor), y mutex, puede estar más relacionado con permitir el acceso a uno a la vez (varias solicitudes para acceder a recursos compartidos, pero solo uno concedido a la vez). [buen artículo: geeksforgeeks.org/mutex-vs-semaphore/]
parasrish

57

Un mutex es un objeto de exclusión mutua, similar a un semáforo pero que solo permite un casillero a la vez y cuyas restricciones de propiedad pueden ser más estrictas que un semáforo.

Se puede considerar como equivalente a un semáforo de conteo normal (con un conteo de uno) y el requisito de que solo puede ser liberado por el mismo hilo que lo bloqueó (a) .

Un semáforo, por otro lado, tiene un recuento arbitrario y puede ser bloqueado por tantos casilleros al mismo tiempo. Y puede que no tenga el requisito de ser liberado por el mismo hilo que lo reclamó (pero, si no es así, debe rastrear cuidadosamente quién tiene actualmente la responsabilidad de ello, al igual que la memoria asignada).

Por lo tanto, si tiene varias instancias de un recurso (por ejemplo, tres unidades de cinta), podría usar un semáforo con un recuento de 3. Tenga en cuenta que esto no le dice cuál de esas unidades de cinta tiene, solo que tiene un cierto número.

También con los semáforos, es posible que un solo casillero bloquee varias instancias de un recurso, como una copia de cinta a cinta. Si tiene un recurso (digamos una ubicación de memoria que no quiere corromper), un mutex es más adecuado.

Las operaciones equivalentes son:

Counting semaphore          Mutual exclusion semaphore
--------------------------  --------------------------
  Claim/decrease (P)                  Lock
  Release/increase (V)                Unlock

Aparte: en caso de que alguna vez se haya preguntado por las letras extrañas que se usan para reclamar y lanzar semáforos, es porque el inventor era holandés. Probeer te verlagen significa intentar disminuir mientras que verhogen significa aumentar.


(a) ... o se puede pensar en algo totalmente distinto de un semáforo, que puede ser más seguro dados sus usos casi siempre diferentes.


De acuerdo, también me encontré con un semáforo binario. ¿Cuándo deberíamos utilizar el semáforo binario y cuándo deberíamos usar mutex?
Karthik Balaguru

Conceptualmente, un semáforo binario es un mutex y es equivalente a un semáforo normal con una cuenta. Puede haber diferencias en las implementaciones del concepto, como la eficiencia o la propiedad del recurso (puede ser liberado por alguien que no sea el reclamante, lo cual no estoy de acuerdo con BTW; un recurso solo debe ser liberado por el hilo que lo reclamó ).
paxdiablo

1
Otra posible diferencia de implementación es el mutex recursivo. Debido a que solo hay un recurso, se puede permitir que un único hilo lo bloquee varias veces (siempre que lo libere tantas veces también). Esto no es tan fácil con un recurso de instancias múltiples ya que es posible que no sepa si el hilo quiere reclamar otra instancia o la misma instancia nuevamente.
paxdiablo

1
Resuelven un problema específico. El hecho de que el problema a resolver es que las personas que no bastante grok mutex, debe de ninguna manera menospreciar la solución :-)
paxdiablo

5
Un mutex es totalmente diferente de un semáforo binario. Lo siento, pero esta definición es incorrecta
Peer Stritzinger

49

¡Es muy importante entender que un mutex no es un semáforo con cuenta 1!

Esta es la razón por la que hay cosas como semáforos binarios (que en realidad son semáforos con cuenta 1).

La diferencia entre un mutex y un semáforo binario es el principio de propiedad:

Un mutex es adquirido por una tarea y por lo tanto también debe ser liberado por la misma tarea. Esto hace posible solucionar varios problemas con semáforos binarios (liberación accidental, interbloqueo recursivo e inversión de prioridad).

Advertencia: escribí "lo hace posible", si y cómo se solucionan estos problemas depende de la implementación del sistema operativo.

Debido a que el mutex debe ser liberado por la misma tarea, no es muy bueno para la sincronización de tareas. Pero si se combina con variables de condición, se obtienen bloques de construcción muy poderosos para construir todo tipo de primitivas ipc.

Entonces, mi recomendación es: si tiene mutexes implementados limpiamente y variables de condición (como con los pthreads POSIX), use estos.

Use semáforos solo si se ajustan exactamente al problema que está tratando de resolver, no intente construir otras primitivas (por ejemplo, rw-locks fuera de los semáforos, use mutex y variables de condición para estos)

Hay muchos malentendidos mutex y semáforos. La mejor explicación que encontré hasta ahora está en este artículo de 3 partes:

Mutex vs.Semaphores - Parte 1: Semáforos

Mutex frente a semáforos - Parte 2: El mutex

Mutex vs semáforos - Parte 3 (parte final): Problemas de exclusión mutua


Las direcciones URL de este sitio contienen caracteres originales y no funcionan, por lo tanto ... Estoy trabajando en ello
Peer Stritzinger

13

Si bien la respuesta de @opaxdiablo es totalmente correcta, me gustaría señalar que el escenario de uso de ambas cosas es bastante diferente. El mutex se usa para proteger partes del código de la ejecución simultánea, los semáforos se usan para que un hilo indique que se ejecute otro hilo.

/* Task 1 */
pthread_mutex_lock(mutex_thing);
    // Safely use shared resource
pthread_mutex_unlock(mutex_thing);



/* Task 2 */
pthread_mutex_lock(mutex_thing);
   // Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex

El escenario del semáforo es diferente:

/* Task 1 - Producer */
sema_post(&sem);   // Send the signal

/* Task 2 - Consumer */
sema_wait(&sem);   // Wait for signal

Consulte http://www.netrino.com/node/202 para obtener más explicaciones.


2
Tienes razón. Incluso si está utilizando un semáforo con una cuenta de uno, está insinuando algo sobre lo que está haciendo que si utiliza un mutex.
Omnifarious

No estoy seguro de estar de acuerdo con eso, aunque no estoy en desacuerdo con tanta vehemencia como para rechazarlo :-) Dices que el patrón de uso de los semáforos es notificar a los hilos, pero eso es exactamente lo que hacen los mutex cuando hay otro hilo esperando en él, y exactamente lo que no hacen los semáforos cuando no hay hilos en sema_wait:-) En mi opinión, ambos se tratan de recursos y la notificación entregada a otros hilos es un efecto secundario (muy importante, en cuanto al rendimiento) del proteccion.
paxdiablo

You say that the usage pattern of semaphores is to notify threadsUn punto sobre la notificación de hilos. Puede llamar sem_postdesde un manejador de señales de manera segura ( pubs.opengroup.org/onlinepubs/009695399/functions/… ) pero no se recomienda llamar pthread_mutex_locky pthread_mutex_unlockdesde manejadores de señales ( manpages.ubuntu.com/manpages/lucid/man3/… )

@paxdiablo: Hay una gran diferencia entre este semáforo binario mutex y es mantener el recuento de referencias. Mutex o puede decir que cualquier mutex condicional no mantiene ningún recuento relacionado con el bloqueo donde se usa el sempahore para mantener el recuento. Entonces sem_wait y sem_post mantienen el conteo.
Prak

9

Consulte "El ejemplo del inodoro" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :

Mutex:

Es la llave de un baño. Una persona puede tener la llave (ocupar el baño) en ese momento. Cuando termina, la persona entrega (libera) la llave a la siguiente persona en la cola.

Oficialmente: "Los mutex se utilizan normalmente para serializar el acceso a una sección de código reentrante que no puede ser ejecutado simultáneamente por más de un hilo. Un objeto mutex solo permite que un hilo entre en una sección controlada, lo que obliga a otros hilos que intentan obtener acceso a esa sección para esperar hasta que el primer hilo haya salido de esa sección ". Ref: Biblioteca de desarrolladores de Symbian

(Un mutex es realmente un semáforo con valor 1.)

Semáforo:

Es el número de llaves de baño idénticas y gratuitas. Por ejemplo, digamos que tenemos cuatro baños con cerraduras y llaves idénticas. El recuento del semáforo, el recuento de llaves, se establece en 4 al principio (los cuatro inodoros son gratuitos), luego el valor del recuento disminuye a medida que las personas entran. Si todos los inodoros están llenos, es decir. no quedan claves libres, el recuento de semáforos es 0. Ahora, cuando eq. una persona sale del baño, el semáforo se aumenta a 1 (una tecla libre) y se entrega a la siguiente persona en la cola.

Oficialmente: "Un semáforo restringe el número de usuarios simultáneos de un recurso compartido hasta un número máximo. Los subprocesos pueden solicitar acceso al recurso (disminuyendo el semáforo) y pueden indicar que han terminado de usar el recurso (aumentando el semáforo). " Ref: Biblioteca de desarrolladores de Symbian


7

Intento no sonar loco, pero no puedo evitarlo.

Su pregunta debería ser ¿cuál es la diferencia entre mutex y semáforos? Y para ser más precisos, la pregunta debería ser, '¿cuál es la relación entre mutex y semáforos?'

(Habría agregado esa pregunta, pero estoy 100% seguro de que algún moderador demasiado entusiasta la cerraría como duplicada sin entender la diferencia entre diferencia y relación).

En terminología de objetos podemos observar que:

observación.1 El semáforo contiene mutex

observación.2 El mutex no es semáforo y el semáforo no es mutex.

Hay algunos semáforos que actuarán como si fueran mutex, llamados semáforos binarios, pero NO son mutex.

Hay un ingrediente especial llamado Señalización (posix usa condition_variable para ese nombre), requerido para hacer un semáforo a partir de mutex. Piense en ello como una fuente de notificación. Si dos o más hilos están suscritos a la misma fuente de notificación, entonces es posible enviarles un mensaje a UNO o a TODOS, para despertar.

Podría haber uno o más contadores asociados con semáforos, que están protegidos por mutex. El escenario más simple para el semáforo, hay un solo contador que puede ser 0 o 1.

Aquí es donde la confusión se derrama como lluvia monzónica.

Un semáforo con un contador que puede ser 0 o 1 NO es mutex.

Mutex tiene dos estados (0,1) y una propiedad (tarea). El semáforo tiene un mutex, algunos contadores y una variable de condición.

Ahora, use su imaginación, y cada combinación de uso de contador y cuándo señalar puede hacer un tipo de semáforo.

  1. Contador único con valor 0 o 1 y señalización cuando el valor pasa a 1 Y luego desbloquea a uno de los tipos que esperan la señal == Semáforo binario

  2. Contador único con valor de 0 a N y que indica cuando el valor desciende por debajo de N, y se bloquea / espera cuando los valores son N == Semáforo de recuento

  3. Contador único con valor de 0 a N y que indica cuando el valor pasa a N, y se bloquea / espera cuando los valores son inferiores a N == Semáforo de barrera (bueno, si no lo llaman, entonces deberían hacerlo).

Ahora a su pregunta, cuándo usar qué. (O en lugar de corregir la versión de la pregunta.3 cuándo usar mutex y cuándo usar binary-semáforo, ya que no hay comparación con el semáforo no binario.) Use mutex cuando 1. desee un comportamiento personalizado, que no sea proporcionado por binary semáforo, tales como bloqueo de giro o bloqueo rápido o bloqueos recursivos. Por lo general, puede personalizar los mutex con atributos, pero personalizar el semáforo no es más que escribir un nuevo semáforo. 2. quieres un primitivo ligero o más rápido

Utilice semáforos, cuando lo que desea se lo proporciona exactamente.

Si no comprende lo que proporciona su implementación de binary-semaphore, en mi humilde opinión, use mutex.

Y, por último, lea un libro en lugar de confiar solo en SO.


5

Creo que la pregunta debería ser la diferencia entre mutex y semáforo binario.

Mutex = Es un mecanismo de bloqueo de propiedad, solo el hilo que adquiere el bloqueo puede liberarlo.

binary Semaphore = Es más un mecanismo de señal, cualquier otro hilo de mayor prioridad si lo desea puede señalar y tomar el bloqueo.


5

Mutex es para proteger el recurso compartido.
El semáforo es enviar los hilos.

Mutex:
Imagina que hay algunas entradas para vender. Podemos simular un caso en el que muchas personas compran las entradas al mismo tiempo: cada persona es un hilo para comprar entradas. Obviamente, necesitamos usar el mutex para proteger los tickets porque es el recurso compartido.


Semáforo:
Imagine que necesitamos hacer un cálculo como se muestra a continuación:

c = a + b;

Además, necesitamos una función geta()para calcular a, una función getb()para calcular by una función getc()para hacer el cálculo c = a + b.

Obviamente, no podemos hacer el a c = a + bmenos que geta()y getb()haya terminado.
Si las tres funciones son tres subprocesos, necesitamos distribuir los tres subprocesos.

int a, b, c;
void geta()
{
    a = calculatea();
    semaphore_increase();
}

void getb()
{
    b = calculateb();
    semaphore_increase();
}

void getc()
{
    semaphore_decrease();
    semaphore_decrease();
    c = a + b;
}

t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);

Con la ayuda del semáforo, el código anterior puede asegurarse de que t3no va a hacer su trabajo hasta el t1y t2han hecho su trabajo.

En una palabra, semáforo es hacer que los hilos se ejecuten como un orden lógico, mientras que mutex es para proteger el recurso compartido.
Entonces NO son lo mismo incluso si algunas personas siempre dicen que mutex es un semáforo especial con el valor inicial 1. También puede decir esto, pero tenga en cuenta que se usan en diferentes casos. No reemplace uno por otro incluso si puede hacerlo.


La venta de entradas es un buen ejemplo. El ejemplo de semáforo no está claro (para mí de todos modos).
prayagupd

1
@prayagupd El ejemplo de Semaphore es hacer hilos en algún orden, mientras que vender boletos no necesita ningún orden. Si hay tres personas: a, by c. Cuando vienen a comprar entradas, no nos importa en absoluto el orden de compra de las entradas. Sin embargo, si hacemos tal cálculo: x = getx(); y = gety(); z = x + y;por alguna razón, usamos tres hilos para hacer las tres cosas, ahora el orden de los hilos es muy importante porque no podemos hacerlo a x + ymenos que getxy getyhayamos terminado. En una palabra, el semáforo se usa cuando nos preocupamos por el orden de ejecución de los subprocesos múltiples.
Yves

te tengo. Suena similar a barrera . Puedo decir que espere hasta que los hilos xy yse completen, luego calcule z = x + y. Sé que Java tiene CyclicBarrier. Además, no estoy seguro de poder decir que mapreducees un caso de uso de semáforo también, porque no puedo reducehasta que mapse completen todos los correos electrónicos .
prayagupd

@prayagupd Sí. Puedes decir eso.
Yves

2

Todas las respuestas anteriores son de buena calidad, pero esta es solo para memorizar. El nombre Mutex se deriva de Mutuamente Exclusivo, por lo que está motivado a pensar en un bloqueo de mutex como Exclusión Mutua entre dos como en uno solo a la vez, y si yo Lo poseyó, puede tenerlo solo después de que lo suelte. Por otro lado, tal caso no existe porque Semaphore es como una señal de tráfico (que la palabra Semaphore también significa).


1

Como se señaló, un semáforo con una cuenta de uno es lo mismo que un semáforo 'binario', que es lo mismo que un mutex.

Las principales cosas que he visto para los semáforos con un recuento mayor que uno usado son situaciones de productor / consumidor en las que tienes una cola de un cierto tamaño fijo.

Entonces tienes dos semáforos. El primer semáforo se establece inicialmente para que sea el número de elementos en la cola y el segundo semáforo se establece en 0. El productor realiza una operación P en el primer semáforo, lo agrega a la cola. y hace una operación V en el segundo. El consumidor realiza una operación P en el segundo semáforo, elimina de la cola y luego realiza una operación V en el primero.

De esta forma, el productor se bloquea siempre que llena la cola y el consumidor se bloquea cuando la cola está vacía.


1

Un mutex es un caso especial de semáforo. Un semáforo permite que varios hilos entren en la sección crítica. Al crear un semáforo, define cómo se permiten los subprocesos en la sección crítica. Por supuesto, su código debe poder manejar varios accesos a esta sección crítica.


-1

El semáforo binario y Mutex son diferentes. Desde la perspectiva del sistema operativo, un semáforo binario y un semáforo de conteo se implementan de la misma manera y un semáforo binario puede tener un valor de 0 o 1.

Mutex -> Solo se puede usar para un solo propósito de exclusión mutua para una sección crítica del código.

Semáforo -> Puede usarse para resolver una variedad de problemas. Se puede utilizar un semáforo binario para la señalización y también resolver el problema de exclusión mutua. Cuando se inicializa a 0 , resuelve el problema de señalización y cuando se inicializa a 1 , resuelve el problema de exclusión mutua .

Cuando la cantidad de recursos es mayor y es necesario sincronizar, podemos usar el semáforo de conteo.

En mi blog, he discutido estos temas en detalle.

https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.