Diferencia entre semáforo binario y mutex


819

¿Hay alguna diferencia entre un semáforo binario y un mutex o son esencialmente lo mismo?


11
Son semánticamente iguales, pero en la práctica notará diferencias extrañas (especialmente en Windows).
Michael Foukarakis

55
@ Michael Foukarakis: ¿Cuáles son las diferencias extrañas?
Philipp

2
Supongo que extraño no era la expresión correcta. Un mutex también admite propiedad y, a veces, reingreso. Este es el caso en Windows. Además, los semáforos en Windows se implementan sobre los objetos de evento, sin embargo, no estoy seguro de las implicaciones prácticas de esto.
Michael Foukarakis


2
@philipxy Muy bien escondió 'rn' en lugar de 'm'.
Mooncrater

Respuestas:


691

NO son lo mismo. ¡Se utilizan para diferentes propósitos!
Si bien ambos tipos de semáforos tienen un estado lleno / vacío y usan la misma API, su uso es muy diferente.

Semáforos de exclusión
mutua Los semáforos de exclusión mutua se utilizan para proteger los recursos compartidos (estructura de datos, archivo, etc.).

Un semáforo Mutex es "propiedad" de la tarea que lo lleva. Si la Tarea B intenta dar un mutex actualmente en manos de la Tarea A, la llamada de la Tarea B devolverá un error y fallará.

Mutexes siempre usan la siguiente secuencia:

  - SemTake
  - Sección crítica
  - SemGive

Aquí hay un ejemplo simple:

  Hilo A Hilo B
   Tomar mutex
     datos de acceso
     ... Tome Mutex <== Bloqueará
     ...
   Dar datos de acceso Mutex <== Desbloquea
                                  ...
                                Dar mutex

Semáforo binario El semáforo
binario aborda una pregunta totalmente diferente:

  • La tarea B está en espera de que ocurra algo (por ejemplo, un sensor se disparó).
  • El sensor se dispara y se ejecuta una rutina de servicio de interrupción. Necesita notificar una tarea del viaje.
  • La tarea B debe ejecutarse y tomar las medidas apropiadas para el disparo del sensor. Luego vuelve a esperar.

   Task A                      Task B
   ...                         Take BinSemaphore   <== wait for something
   Do Something Noteworthy
   Give BinSemaphore           do something    <== unblocks

Tenga en cuenta que con un semáforo binario, está bien que B tome el semáforo y A lo dé.
Una vez más, un semáforo binario NO está protegiendo un recurso del acceso. El acto de dar y tomar un semáforo está fundamentalmente desacoplado.
Por lo general, no tiene mucho sentido que la misma tarea sea un dar y tomar el mismo semáforo binario.


12
¿No es un mutex mejor que un semáforo binario entonces? Dado que no tiene sentido si alguien libera un candado que en realidad no tiene.
Pacerier

111
Tienen diferentes propósitos. Mutex es para acceso exclusivo a un recurso. Se debe utilizar un semáforo binario para la sincronización (es decir, "¡Oye, alguien! ¡Esto ocurrió!"). El "dador" binario simplemente notifica a quien sea el "tomador" que sucedió lo que estaban esperando.
Benoit

55
@Pacerier Estás confundiendo el propósito. Se pretende que un mutex proteja una región crítica. Tienes razón, no tiene sentido usar un semáforo binario. Actualizaré la respuesta para explicar el propósito de cada uno.
Benoit

44
@Benoit Entonces, ¿podemos decir que Mutex se usa para la atomicidad y el semáforo binario para la perspectiva de pedidos ya que la Tarea B estará esperando que la Tarea A señale la liberación del bloqueo inherentemente asegurándose de ordenar las operaciones en una estructura de datos?
abhi

1
@abhi Esa es una buena manera de verlo para el Mutex. Sin embargo, dependiendo del sistema operativo, puede tener más de un destinatario esperando en un semáforo binario. En ese caso, solo uno de los clientes obtendrá el sem binario. El (los) otro (s) esperaría por uno posterior. ¿Se conoce o garantiza el orden de recepción? Depende del sistema operativo.
Benoit

446
  • Un mutex solo puede ser liberado por el hilo que lo adquirió .
  • Un semáforo binario puede ser señalado por cualquier hilo (o proceso).

Por lo tanto, los semáforos son más adecuados para algunos problemas de sincronización como productor-consumidor.

En Windows, los semáforos binarios son más como objetos de evento que mutexes.


34
Mutex can be released only by thread that had acquired it- Acabo de probar con un simple programa basado en pthread_mutex, un hilo puede desbloquear mutex bloqueado en el hilo principal
daisy

15
@ warl0ck Según la página de manual de pthread_mutex_lock linux.die.net/man/3/pthread_mutex_lock : "Si el tipo de mutex es PTHREAD_MUTEX_ERRORCHECK, se proporcionará una comprobación de errores ... Si un hilo intenta desbloquear un mutex que tiene no bloqueado o un mutex que está desbloqueado, se devolverá un error ".
amit el

47
@ warl0ck Consulte stackoverflow.com/a/5492499/385064 'Pthreads tiene 3 tipos diferentes de mutexes: mutex rápido, mutex recursivo y mutex de verificación de errores. Usó un mutex rápido que, por razones de rendimiento, no verificará este error. Si utiliza el error de comprobación de mutex en Linux, encontrará que obtiene los resultados que espera '.
FrostNovaZzz

1
En nuestro código, hemos usado mutex también para fines de sincronización. El hilo que bloquea el mutex nuevamente trató de bloquear el mutex. Luego pasa al estado bloqueado. Lo que hemos visto es que podemos desbloquear esto desde otro hilo. Sincronización entre los dos. Solo estamos utilizando el estándar posix. Por lo tanto, la principal diferencia entre mutex y semáforo binario parece vaga.
achoora

1
@achoora Estoy de acuerdo en que está mal especializar el semáforo para la sincronización. En realidad, todos los mutex, semáforos binarios, barreras, tuberías son patrones diferentes para la sincronización. En la perspectiva del diseño, los mutex son más como un patrón de estado donde el algoritmo seleccionado por el estado puede cambiar el estado. Los semáforos binarios son más como un patrón de estrategia donde el algoritmo externo puede cambiar el estado y, finalmente, el algoritmo / estrategia seleccionado para ejecutarse.
Shuva

442

El ejemplo del inodoro es una analogía agradable:

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 le da (libera) la clave a la siguiente persona en la cola.

Oficialmente: "Los mutex se suelen usar para serializar el acceso a una sección de código entrante que no puede ejecutarse simultáneamente por más de un subproceso. Un objeto mutex solo permite un subproceso en una sección controlada, forzando a otros subprocesos 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 inodoro idénticas gratuitas. Ejemplo, digamos que tenemos cuatro baños con cerraduras y llaves idénticas. El recuento de semáforos, el recuento de llaves, se establece en 4 al principio (los cuatro inodoros son gratuitos), luego el valor del recuento disminuye a medida que entran personas. Si todos los inodoros están llenos, es decir. no quedan teclas libres, el recuento de semáforos es 0. Ahora, cuando la ecuación. una persona sale del baño, el semáforo se incrementa a 1 (una clave gratis) y se le da 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 (incrementando el semáforo). " Ref: Biblioteca de desarrolladores de Symbian


234
... pero esto se trata de mutex vs contar semáforo. Se hizo la pregunta sobre binario.
Roman Nikitchenko

24
Si bien lo que dice David es correcto, NO es la respuesta a la pregunta formulada. La respuesta de Mladen Jankovic es la respuesta a la pregunta formulada, donde se hace un punto para diferenciar "semáforo binario" frente a "mutex".
Ajeet Ganga

13
Desafortunadamente, esta respuesta incorrecta tiene más votos que la mejor respuesta de @Benoit
NeonGlow

66
Esta respuesta es engañosa. Debería haberse comparado solo con el semáforo binario.
Hemanth

3
Esto también demuestra un problema con el uso de un semáforo de conteo para proteger un recurso compartido: si las llaves son realmente idénticas, y un inodoro se desbloquea usando una llave, y no hay otro mecanismo para distribuir el uso del cubículo, entonces: (1) el primero el usuario desbloquea, ingresa y comienza a usar el primer cubículo. (2) el siguiente usuario desbloquea, ingresa y comienza a usar el primer cubículo ...
Technophile

151

Buenos artículos sobre el tema:

De la parte 2:

El mutex es similar a los principios del semáforo binario con una diferencia significativa: el principio de propiedad. La propiedad es el concepto simple de que cuando una tarea bloquea (adquiere) un mutex solo puede desbloquearlo (liberarlo). Si una tarea intenta desbloquear un mutex que no se ha bloqueado (por lo tanto, no posee), se encuentra una condición de error y, lo más importante, el mutex no se desbloquea. Si el objeto de exclusión mutua no tiene propiedad, irrelevante de lo que se llama, no es un mutex.


Gracias por el enlace, las explicaciones allí son excelentes. El enlace ha cambiado: feabhas.com/blog/2009/09/… (Use <Anterior y Siguiente> para navegar a los otros dos artículos.
Aaron H.

@ Aaron arregle los enlaces
Juez Maygarden

Nota: la falta de propiedad también evita que el sistema operativo trabaje alrededor de la inversión de prioridad. Por esta razón, generalmente uso variables de condición en lugar de semáforos para arquitecturas de productor / consumidor.
kgriffs

1
+1 enemigos excelentes enlaces de artículos. El mejor artículo que explica el semáforo y el mutex con "what-it-is" y "what-it-it" computing.llnl.gov/tutorials/pthreads. Utilicé este artículo como mi referencia detrás de escena, que técnicamente explica todo sobre mutex / condicionales y otras construcciones construidas en su parte superior como semáforo / barrera / lector-escritor, pero en ningún lugar explícito y conciso sobre los problemas que enfrentan las construcciones. En resumen es referencia. :)
Ajeet Ganga

más fácilmente entendido que las otras respuestas.
BinaryTreeee

101

Como ninguna de las respuestas anteriores aclara la confusión, aquí hay una que despejó mi confusión.

Estrictamente hablando, un mutex es un mecanismo de bloqueo utilizado para sincronizar el acceso a un recurso. Solo una tarea (puede ser un subproceso o un proceso basado en la abstracción del sistema operativo) puede adquirir el mutex. Significa que habrá propiedad asociada con mutex, y solo el propietario puede liberar el bloqueo (mutex).

El semáforo es un mecanismo de señalización (tipo de señal "He terminado, puedes continuar"). Por ejemplo, si está escuchando canciones (suponga que es una tarea) en su teléfono móvil y al mismo tiempo que su amigo lo llamó, se activará una interrupción en la que una rutina de servicio de interrupción (ISR) indicará que la tarea de procesamiento de llamadas se activará .

Fuente: http://www.geeksforgeeks.org/mutex-vs-semaphore/


42

Su semántica de sincronización es muy diferente:

  • los mutexes permiten la serialización del acceso a un recurso dado, es decir, varios subprocesos esperan un bloqueo, uno a la vez y, como se dijo anteriormente, el subproceso posee el bloqueo hasta que se realiza: solo este subproceso particular puede desbloquearlo.
  • un semáforo binario es un contador con valor 0 y 1: una tarea que lo bloquea hasta que cualquier tarea realiza un sem_post. El semáforo anuncia que hay un recurso disponible y proporciona el mecanismo para esperar hasta que se indique que está disponible.

Como tal, se puede ver un mutex como un token pasado de una tarea a otra y un semáforo como semáforo en rojo ( indica a alguien que puede continuar).


23

A nivel teórico, no son semánticamente diferentes. Puede implementar un mutex utilizando semáforos o viceversa (vea aquí un ejemplo). En la práctica, la implementación es diferente y ofrecen servicios ligeramente diferentes.

La diferencia práctica (en términos de los servicios del sistema que los rodean) es que la implementación de un mutex tiene como objetivo ser un mecanismo de sincronización más liviano. En oracle-speak, los mutex se conocen como pestillos y los semáforos se conocen como esperas .

En el nivel más bajo, utilizan algún tipo de prueba atómica y mecanismo de ajuste . Esto lee el valor actual de una ubicación de memoria, calcula algún tipo de condicional y escribe un valor en esa ubicación en una sola instrucción que no se puede interrumpir . Esto significa que puede adquirir un mutex y probar para ver si alguien más lo tuvo antes que usted.

Una implementación típica de mutex tiene un proceso o subproceso que ejecuta la instrucción test-and-set y evalúa si algo más ha establecido el mutex. Un punto clave aquí es que no hay interacción con el planificador , por lo que no tenemos idea (y no me importa) quién ha establecido el bloqueo. Luego, renunciamos a nuestro intervalo de tiempo e intentamos nuevamente cuando la tarea se reprograma o ejecutamos un spin-lock . Un bloqueo de giro es un algoritmo como:

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

Cuando terminemos de ejecutar nuestro código protegido (conocido como sección crítica ), simplemente establecemos el valor de mutex en cero o lo que sea 'claro'. Si varias tareas intentan adquirir el mutex, la siguiente tarea que se programe después de que se libere el mutex tendrá acceso al recurso. Por lo general, usaría mutexes para controlar un recurso sincronizado donde el acceso exclusivo solo es necesario por períodos muy cortos de tiempo, normalmente para actualizar una estructura de datos compartida.

Un semáforo es una estructura de datos sincronizada (típicamente usando un mutex) que tiene un conteo y algunos contenedores de llamadas del sistema que interactúan con el planificador en un poco más de profundidad que las bibliotecas mutex. Los semáforos se incrementan y disminuyen y se usan para bloquear tareas hasta que algo más esté listo. Vea el problema del productor / consumidor para un ejemplo simple de esto. Los semáforos se inicializan a algún valor: un semáforo binario es solo un caso especial en el que el semáforo se inicializa a 1. La publicación en un semáforo tiene el efecto de despertar un proceso de espera.

Un algoritmo de semáforo básico se ve así:

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

En el caso de un semáforo binario, la principal diferencia práctica entre los dos es la naturaleza de los servicios del sistema que rodean la estructura de datos real.

EDITAR: como evan ha señalado correctamente, los spinlocks ralentizarán una máquina con un solo procesador. Solo usaría un spinlock en una caja multiprocesador porque en un solo procesador el proceso que contiene el mutex nunca lo restablecerá mientras se esté ejecutando otra tarea. Los Spinlocks solo son útiles en arquitecturas multiprocesador.


1
No creo que sea una práctica común implementar un mutex con spinlocks. En una máquina Uni-proc, esto sería absolutamente terrible para el rendimiento.
Evan Teran

Normalmente solo usaría spinlocks en sistemas multiprocesador.
Preocupado por

Incluso en SMP, después de girar varias veces, recurre al sueño / vigilia asistido por el sistema operativo. (por ejemplo, la futexllamada al sistema Linux existe para ayudar a las implementaciones de mutex / semáforo de espacio de usuario de baja latencia. en.wikipedia.org/wiki/Futex ) En la ruta rápida sin contención, o si el recurso está disponible pronto, nunca tendrá la sobrecarga de Una llamada al sistema. Pero no pasa más de unos pocos microsegundos ocupados esperando (girando). Ajustar los parámetros de retroceso y espera del bucle giratorio depende del hardware y la carga de trabajo, por supuesto, pero la biblioteca estándar generalmente tiene opciones razonables.
Peter Cordes

19

Aunque los mutex y los semáforos se usan como primitivas de sincronización, existe una gran diferencia entre ellos. En el caso de mutex, solo el hilo que bloqueó o adquirió el mutex puede desbloquearlo. En el caso de un semáforo, un hilo que espera en un semáforo puede ser señalado por un hilo diferente. Algunos sistemas operativos admiten el uso de mutex y semáforos entre procesos. Normalmente, el uso se crea en la memoria compartida.


"puede ser señalado por un hilo diferente", ¿qué significa dar un ejemplo?
Myanju

15

Mutex: Supongamos que tenemos una sección crítica que el hilo T1 quiere acceder, luego sigue los siguientes pasos. T1:

  1. Bloquear
  2. Usar sección crítica
  3. desbloquear

Semáforo binario: Funciona en función de la señalización de espera y señal. espere (s) disminuya el valor "s" en uno, generalmente el valor "s" se inicializa con el valor "1", la señal (es) aumenta el valor "s" en uno. si el valor "s" es 1 significa que nadie está usando la sección crítica, cuando el valor es 0 significa que la sección crítica está en uso. supongamos que el hilo T2 está usando la sección crítica y luego sigue los pasos a continuación. T2:

  1. wait (s) // inicialmente el valor es uno después de llamar a wait su valor disminuyó en uno, es decir, 0
  2. Usar sección crítica
  3. señal (es) // ahora el valor de s aumenta y se convierte en 1

La principal diferencia entre el semáforo Mutex y el binario está en Mutext si el subproceso bloquea la sección crítica, entonces tiene que desbloquear la sección crítica, ningún otro subproceso puede desbloquearlo, pero en el caso del semáforo binario si un subproceso bloquea la sección crítica utilizando la función de espera (s), entonces el valor de s se convierte en "0" y nadie puede acceder a él hasta que el valor de "s" se convierta en 1, pero suponga que alguna otra llamada de hilo señala (s), luego el valor de "s" se convierte en 1 y permite que otra función use la sección crítica. por lo tanto, en el hilo de semáforo binario no tiene propiedad.


12

En Windows, hay dos diferencias entre mutexes y semáforos binarios:

  1. Un mutex solo puede ser liberado por el hilo que tiene la propiedad, es decir, el hilo que anteriormente llamó a la función Esperar, (o que tomó posesión al crearlo). Un semáforo puede ser liberado por cualquier hilo.

  2. Un hilo puede llamar a una función de espera repetidamente en un mutex sin bloquear. Sin embargo, si llama a una función de espera dos veces en un semáforo binario sin liberar el semáforo en el medio, el hilo se bloqueará.


44
Buena respuesta. En el n. ° 2, está describiendo un mutex recursivo; no todos los mutexes son necesariamente recursivos. Por ejemplo, cs.wustl.edu/~schmidt/ACE.FAQ.html#Q14
Dan

10

Obviamente, usa mutex para bloquear datos en un hilo al que otro hilo accede al mismo tiempo. Asume que acabas de llamarlock() y en el proceso de acceso a los datos. Esto significa que no espera que ningún otro hilo (u otra instancia del mismo código de hilo) acceda a los mismos datos bloqueados por el mismo mutex. Es decir, si es el mismo código de subproceso que se ejecuta en una instancia de subproceso diferente, golpea el bloqueo, entonces ellock()debería bloquear el flujo de control allí. Esto se aplica a un subproceso que utiliza un código de subproceso diferente, que también está accediendo a los mismos datos y que también está bloqueado por el mismo mutex. En este caso, todavía está en el proceso de acceder a los datos y puede tomar, por ejemplo, otros 15 segundos para alcanzar el desbloqueo de mutex (para que el otro hilo que se bloquea en el bloqueo de mutex se desbloquee y permita que el control acceder a los datos). ¿A cualquier costo permite que otro hilo simplemente desbloquee el mismo mutex y, a su vez, permita que el hilo que ya está esperando (bloqueando) en el bloqueo de mutex se desbloquee y acceda a los datos? ¿Espero que hayas entendido lo que digo aquí? Según lo acordado, definición universal!

  • con "mutex" esto no puede suceder. Ningún otro hilo puede desbloquear el bloqueo en tu hilo
  • con "semáforo binario" esto puede suceder. Cualquier otro hilo puede desbloquear el bloqueo en tu hilo

Por lo tanto, si usted es muy particular sobre el uso de semáforos binarios en lugar de mutex, entonces debe tener mucho cuidado al "determinar" los bloqueos y desbloqueos. Quiero decir que cada flujo de control que golpea cada bloqueo debe golpear una llamada de desbloqueo, también no debe haber ningún "primer desbloqueo", sino que siempre debe ser "primer bloqueo".


10

Los mutex se utilizan para "mecanismos de bloqueo". un proceso a la vez puede usar un recurso compartido

mientras

Los semáforos se usan para "Mecanismos de señalización" como "Ya terminé, ahora puede continuar"


9

Mito:

Un par de artículos dice que "el semáforo binario y el mutex son iguales" o "el semáforo con el valor 1 es mutex", pero la diferencia básica es que Mutex solo puede liberarse mediante un hilo que lo haya adquirido, mientras que puede señalar el semáforo desde cualquier otro hilo

Puntos clave:

• Un subproceso puede adquirir más de un bloqueo (Mutex).

• Un mutex se puede bloquear más de una vez solo si es un mutex recursivo, aquí el bloqueo y desbloqueo para mutex debe ser el mismo

• Si un hilo que ya había bloqueado un mutex, intenta bloquear el mutex nuevamente, entrará en la lista de espera de ese mutex, lo que resulta en un punto muerto.

• El semáforo binario y el mutex son similares pero no iguales.

• Mutex es una operación costosa debido a los protocolos de protección asociados.

• El objetivo principal de mutex es lograr el acceso atómico o bloquear el recurso


8

Un Mutex controla el acceso a un único recurso compartido. Proporciona operaciones para adquirir () acceso a ese recurso y liberarlo () cuando haya terminado.

Un semáforo controla el acceso a un grupo compartido de recursos. Proporciona operaciones a Wait () hasta que uno de los recursos del grupo esté disponible, y Signal () cuando se devuelve al grupo.

Cuando el número de recursos que protege un semáforo es mayor que 1, se llama semáforo de conteo . Cuando controla un recurso, se llama un semáforo booleano . Un semáforo booleano es equivalente a un mutex.

Por lo tanto, un semáforo es un nivel de abstracción más alto que Mutex. Un Mutex se puede implementar usando un semáforo pero no al revés.


6

La pregunta modificada es: ¿Cuál es la diferencia entre un mutex y un semáforo "binario" en "Linux"?

Respuesta: Las siguientes son las diferencias: i) Alcance: el alcance de mutex está dentro de un espacio de direcciones de proceso que lo ha creado y se utiliza para la sincronización de subprocesos. Mientras que el semáforo se puede usar en todo el espacio del proceso y, por lo tanto, se puede usar para la sincronización entre procesos.

ii) Mutex es ligero y más rápido que el semáforo. Futex es aún más rápido.

iii) Mutex puede ser adquirido por el mismo subproceso con éxito varias veces con la condición de que lo libere el mismo número de veces. Se bloqueará otro hilo que intente adquirir. Mientras que en caso de semáforo, si el mismo proceso intenta adquirirlo nuevamente, se bloquea, ya que solo se puede adquirir una vez.


i) Incorrecto ii) Fuente? iii) Depende.
curioso

6

Diferencia entre semáforo binario y mutex: PROPIEDAD: los semáforos se pueden señalar (publicar) incluso desde un propietario no actual. Significa que puedes simplemente publicar desde cualquier otro hilo, aunque no eres el propietario.

El semáforo es una propiedad pública en proceso, simplemente puede ser publicado por un hilo no propietario. Marque esta diferencia en negrita, significa mucho.


5

Mutex trabaja en el bloqueo de la región crítica, pero Semaphore trabaja en la cuenta.



4

Además del hecho de que los mutexes tienen un propietario, los dos objetos pueden optimizarse para un uso diferente. Los mutexes están diseñados para mantenerse solo por un corto tiempo; violar esto puede causar un bajo rendimiento y una programación injusta. Por ejemplo, se puede permitir que un hilo en ejecución adquiera un mutex, aunque otro hilo ya esté bloqueado en él. Los semáforos pueden proporcionar más justicia, o la justicia puede ser forzada usando varias variables de condición.


¿En qué casos específicos se garantiza la equidad para los semáforos pero no para los mutexes?
curioso

1
POSIX tiene requisitos específicos cuál de ellos hay despertado por sem_post()para SCHED_FIFOy SCHED_RR(ambos de estos no están por defecto): la más alta prioridad de hilo, y si hay múltiples con la misma prioridad, el hilo que ha estado esperando más tiempo. OpenSolaris sigue esta regla FIFO hasta cierto punto incluso para la programación normal. Para glibc y FreeBSD, desbloquear un mutex simple (es decir, no proteger con prioridad o heredar con prioridad) y publicar un semáforo son básicamente lo mismo, marcar el objeto como desbloqueado y luego, si puede haber hilos en espera, llamar al núcleo para que active uno.
jilles

4

En windows la diferencia es la siguiente. MUTEX: el proceso que ejecuta con éxito la espera tiene que ejecutar una señal y viceversa. SEMÁFOROS BINARIOS: diferentes procesos pueden ejecutar la operación de espera o señal en un semáforo.


4

Mientras que un semáforo binario se puede usar como un mutex, un mutex es un caso de uso más específico, ya que solo el proceso que bloqueó el mutex se supone que lo desbloquea. Esta restricción de propiedad hace posible proporcionar protección contra:

  • Lanzamiento accidental
  • Punto muerto recursivo
  • Tarea Deadlock Dead

Estas restricciones no siempre están presentes porque degradan la velocidad. Durante el desarrollo de su código, puede habilitar estas comprobaciones temporalmente.

por ejemplo, puede habilitar el atributo de comprobación de errores en su mutex. Se produce un error al volver a comprobar los mutexes EDEADLKsi intentas bloquear el mismo dos veces y EPERMsi desbloqueas un mutex que no es tuyo.

pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);

Una vez inicializado, podemos colocar estos controles en nuestro código de esta manera:

if(pthread_mutex_unlock(&mutex)==EPERM)
 printf("Unlock failed:Mutex not owned by this thread\n");

4

El concepto fue claro para mí después de repasar las publicaciones anteriores. Pero había algunas preguntas persistentes. Entonces, escribí este pequeño fragmento de código.

Cuando tratamos de dar un semáforo sin tomarlo, pasa. Pero, cuando intenta dar un mutex sin tomarlo, falla. Probé esto en una plataforma Windows. Habilite USE_MUTEX para ejecutar el mismo código usando un MUTEX.

#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1

DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );

HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;


int main(void)
{

#ifdef USE_MUTEX
    ghMutex = CreateMutex( NULL, FALSE, NULL);
    if (ghMutex  == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }
#else
    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
    ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }
#endif
    // Create thread 1.
    Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);  
    if ( Handle_Of_Thread_1 == NULL)
    {
        printf("Create first thread problem \n");
        return 1;
    }

    /* sleep for 5 seconds **/
    Sleep(5 * 1000);

    /*Create thread 2 */
    Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);  
    if ( Handle_Of_Thread_2 == NULL)
    {
        printf("Create second thread problem \n");
        return 1;
    }

    // Sleep for 20 seconds
    Sleep(20 * 1000);

    printf("Out of the program \n");
    return 0;
}


int my_critical_section_code(HANDLE thread_handle)
{

#ifdef USE_MUTEX
    if(thread_handle == Handle_Of_Thread_1)
    {
        /* get the lock */
        WaitForSingleObject(ghMutex, INFINITE);
        printf("Thread 1 holding the mutex \n");
    }
#else
    /* get the semaphore */
    if(thread_handle == Handle_Of_Thread_1)
    {
        WaitForSingleObject(ghSemaphore, INFINITE);
        printf("Thread 1 holding semaphore \n");
    }
#endif

    if(thread_handle == Handle_Of_Thread_1)
    {
        /* sleep for 10 seconds */
        Sleep(10 * 1000);
#ifdef USE_MUTEX
        printf("Thread 1 about to release mutex \n");
#else
        printf("Thread 1 about to release semaphore \n");
#endif
    }
    else
    {
        /* sleep for 3 secconds */
        Sleep(3 * 1000);
    }

#ifdef USE_MUTEX
    /* release the lock*/
    if(!ReleaseMutex(ghMutex))
    {
        printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
    }
#else
    if (!ReleaseSemaphore(ghSemaphore,1,NULL) )      
    {
        printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
    }
#endif

    return 0;
}

DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
{ 
    my_critical_section_code(Handle_Of_Thread_1);
    return 0;
}


DWORD WINAPI Thread_no_2( LPVOID lpParam ) 
{
    my_critical_section_code(Handle_Of_Thread_2);
    return 0;
}

El hecho mismo de que el semáforo le permite señalar "se hace usando un recurso", aunque nunca haya sido propietario del recurso, me hace pensar que existe un acoplamiento muy flojo entre la posesión y la señalización en el caso de los semáforos.


Si lee las otras respuestas, está claro que el concepto de "propiedad" solo tiene sentido con mutexes, no semáforos. Los semáforos se pueden usar para cosas como un hilo que permite que otros hilos sepan que el procesamiento de una porción de datos se realiza; Resultados listos para ser leídos.
Peter Cordes

2

Mutex se usa para proteger el código y los datos confidenciales, el semáforo se usa para la sincronización. También puede tener un uso práctico para proteger el código sensible, pero puede existir el riesgo de liberar la protección por el otro hilo por la operación V. la diferencia entre bi-semáforo y mutex es la propiedad. Por ejemplo, por inodoro, Mutex es como que uno puede entrar al inodoro y cerrar la puerta, nadie más puede entrar hasta que el hombre salga, el bi-semáforo es como que uno puede entrar el inodoro y cerrar la puerta, pero alguien más podría entrar pidiéndole al administrador que abra la puerta, es ridículo.


2

Mutex

Los mutex generalmente se usan para serializar el acceso a una sección de código entrante que no puede ejecutarse simultáneamente por más de un subproceso. Un objeto mutex solo permite un subproceso en una sección controlada, lo que obliga a otros subprocesos que intentan obtener acceso a esa sección a esperar hasta que el primer subproceso haya salido de esa sección. El uso correcto de un mutex es proteger un recurso compartido puede tener un peligro efecto secundario no deseado Cualquiera de las dos tareas RTOS que operan con diferentes prioridades y se coordinan a través de un mutex, crean la oportunidad para la inversión de prioridad . Mutex funciona en el espacio del usuario .

Semáforo

El semáforo es un mecanismo de señalización. Semaphore 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 (incrementando el semáforo). Permite que varios hilos accedan a recursos compartidos. El uso correcto de un semáforo es para señalizar de una tarea a otra. Los semáforos también se pueden usar para señalar desde una rutina de servicio de interrupción (ISR) a una tarea. La señalización de un semáforo es un comportamiento RTOS sin bloqueo y, por lo tanto, ISR seguro. Debido a que esta técnica elimina la necesidad propensa a errores de deshabilitar las interrupciones a nivel de tarea, esto funciona en el espacio del kernel .


1

La respuesta puede depender del sistema operativo de destino. Por ejemplo, al menos una implementación de RTOS con la que estoy familiarizado permitirá múltiples operaciones secuenciales de "obtención" contra un único mutex del sistema operativo, siempre que estén todas dentro del mismo contexto de subproceso. Los múltiples get deben ser reemplazados por un número igual de puestos antes de que otro hilo pueda obtener el mutex. Esto difiere de los semáforos binarios, para los cuales solo se permite un solo get a la vez, independientemente de los contextos de subprocesos.

La idea detrás de este tipo de mutex es que proteja un objeto al permitir que un solo contexto modifique los datos a la vez. Incluso si el subproceso obtiene el mutex y luego llama a una función que modifica aún más el objeto (y obtiene / coloca el mutex protector alrededor de sus propias operaciones), las operaciones aún deberían ser seguras porque todas ocurren bajo un solo subproceso.

{
    mutexGet();  // Other threads can no longer get the mutex.

    // Make changes to the protected object.
    // ...

    objectModify();  // Also gets/puts the mutex.  Only allowed from this thread context.

    // Make more changes to the protected object.
    // ...

    mutexPut();  // Finally allows other threads to get the mutex.
}

Por supuesto, cuando use esta función, debe estar seguro de que todos los accesos dentro de un solo hilo son realmente seguros.

No estoy seguro de cuán común es este enfoque, o si se aplica fuera de los sistemas con los que estoy familiarizado. Para ver un ejemplo de este tipo de mutex, consulte ThreadX RTOS.


2
El tipo de mutex del que habla se llama "mutex recursivo" y debe evitarse ya que son lentos y tienden a promover un mal diseño: (ver David Butenhof: zaval.org/resources/library/butenhof1.html )
gaspard

Convenido. En este sistema operativo en particular, utilizo el servicio mutex donde quiero dejar en claro que el código es para "exclusión mutua" y no para el recuento de referencias, pero no utilizo la función recursiva por temor a un desenlace feo. Aún así, en el contexto de la pregunta, esta es una diferencia importante entre un "mutex" y un "semáforo binario".
Casey Barker

1

Los mutexes tienen propiedad, a diferencia de los semáforos. Aunque cualquier hilo, dentro del alcance de un mutex, puede obtener un mutex desbloqueado y bloquear el acceso a la misma sección crítica de código, solo el hilo que bloqueó un mutex debe desbloquearlo .


¿Qué es la propiedad? ¿Quieres decir que el contexto que adquiere mutex solo puede deshacerse de él?
Raulp

1

Como muchas personas aquí han mencionado, se usa un mutex para proteger una pieza crítica de código (también conocida como sección crítica). Adquirirá el mutex (bloqueo), ingresará a la sección crítica y liberará mutex (desbloqueo) todo en el mismo hilo .

Mientras usa un semáforo, puede hacer que un hilo espere en un semáforo (digamos el hilo A), hasta que otro hilo (digamos el hilo B) complete cualquier tarea, y luego configure el semáforo para el hilo A para detener la espera y continuar su tarea.


1

Mejor solución

La unica diferencia es

1.Mutex -> bloquear y desbloquear son propiedad de un hilo que bloquea el mutex.

2. Semáforo -> Sin propiedad, es decir; Si un hilo llama a semwait (s), cualquier otro hilo puede llamar a sempost (s) para eliminar el bloqueo.


1

MUTEX

Hasta hace poco, el único candado para dormir en el núcleo era el semáforo. La mayoría de los usuarios de semáforos instanciaron un semáforo con un recuento de uno y los trataron como un bloqueo de exclusión mutua, una versión inactiva del bloqueo de giro. Desafortunadamente, los semáforos son bastante genéricos y no imponen ninguna restricción de uso. Esto los hace útiles para administrar el acceso exclusivo en situaciones oscuras, como bailes complicados entre el núcleo y el espacio de usuario. Pero también significa que un bloqueo más simple es más difícil de hacer, y la falta de reglas forzadas hace imposible cualquier tipo de depuración automática o aplicación de restricciones. Buscando un bloqueo para dormir más simple, los desarrolladores del kernel introdujeron el mutex. Sí, como está acostumbrado, ese es un nombre confuso. Vamos a aclararlo. El término "mutex" es un nombre genérico para referirse a cualquier candado para dormir que obliga a la exclusión mutua, como un semáforo con un recuento de uso de uno. En los núcleos de Linux recientes, el nombre propio "mutex" ahora también es un tipo específico de bloqueo de suspensión que implementa la exclusión mutua. Es decir, un mutex es un mutex.

La simplicidad y la eficiencia del mutex provienen de las restricciones adicionales que impone a sus usuarios más allá de lo que requiere el semáforo. A diferencia de un semáforo, que implementa el comportamiento más básico de acuerdo con el diseño original de Dijkstra, el mutex tiene un caso de uso más estricto y estrecho: n Solo una tarea puede contener el mutex a la vez. Es decir, el recuento de uso en un mutex es siempre uno.

  1. Quien bloqueó un mutex debe desbloquearlo. Es decir, no puede bloquear un mutex en un contexto y luego desbloquearlo en otro. Esto significa que el mutex no es adecuado para sincronizaciones más complicadas entre el núcleo y el espacio de usuario. Sin embargo, la mayoría de los casos de uso se bloquean y desbloquean limpiamente desde el mismo contexto.
  2. Los bloqueos y desbloqueos recursivos no están permitidos. Es decir, no puede adquirir recursivamente el mismo mutex y no puede desbloquear un mutex desbloqueado.
  3. Un proceso no puede salir mientras se mantiene un mutex.
  4. Un mutex no puede ser adquirido por un controlador de interrupciones o la mitad inferior, incluso con mutex_trylock ().
  5. Un mutex solo se puede administrar a través de la API oficial: se debe inicializar a través de los métodos descritos en esta sección y no se puede copiar, inicializar a mano o reinicializar.

[1] Desarrollo del kernel de Linux, tercera edición Robert Love


1

Creo que la mayoría de las respuestas aquí fueron confusas, especialmente aquellas que dicen que mutex solo puede liberarse mediante el proceso que lo contiene, pero el semáforo puede señalarse mediante un proceso. La línea anterior es un poco vaga en términos de semáforo. Para entenderlo, debemos saber que hay dos tipos de semáforos, uno se llama semáforo de conteo y el otro se llama semáforo binario. Al contar, el semáforo maneja el acceso a n número de recursos donde n puede definirse antes del uso. Cada semáforo tiene una variable de recuento, que mantiene el recuento de la cantidad de recursos en uso, inicialmente, se establece en n. Cada proceso que desea utilizar un recurso realiza una operación wait () en el semáforo (disminuyendo así el recuento). Cuando un proceso libera un recurso, realiza una operación release () (incrementando el conteo). Cuando el recuento se convierte en 0, Se están utilizando todos los recursos. Después de eso, el proceso espera hasta que el recuento sea más de 0. Ahora aquí está la captura, solo el proceso que contiene el recurso puede aumentar el recuento, ningún otro proceso puede aumentar el recuento, solo los procesos que contienen un recurso pueden aumentar el recuento y el proceso esperar el semáforo nuevamente verifica y cuando ve el recurso disponible, disminuye el conteo nuevamente. Entonces, en términos de semáforo binario, solo el proceso que contiene el semáforo puede aumentar el recuento, y el recuento permanece en cero hasta que deja de usar el semáforo y aumenta el recuento y otros procesos tienen la oportunidad de acceder al semáforo. Ahora aquí está la captura, solo el proceso que contiene el recurso puede aumentar el recuento, ningún otro proceso puede aumentar el recuento, solo los procesos que retienen un recurso pueden aumentar el recuento y el proceso que espera el semáforo nuevamente verifica y cuando ve que el recurso está disponible Disminuye la cuenta de nuevo. Entonces, en términos de semáforo binario, solo el proceso que contiene el semáforo puede aumentar el recuento, y el recuento permanece en cero hasta que deja de usar el semáforo y aumenta el recuento y otros procesos tienen la oportunidad de acceder al semáforo. Ahora aquí está la captura, solo el proceso que contiene el recurso puede aumentar el recuento, ningún otro proceso puede aumentar el recuento, solo los procesos que contienen un recurso pueden aumentar el recuento y el proceso que espera el semáforo vuelve a verificar y cuando ve que el recurso está disponible, Disminuye la cuenta de nuevo. Entonces, en términos de semáforo binario, solo el proceso que contiene el semáforo puede aumentar el recuento, y el recuento permanece en cero hasta que deja de usar el semáforo y aumenta el recuento y otros procesos tienen la oportunidad de acceder al semáforo.

La principal diferencia entre el semáforo binario y el mutex es que el semáforo es un mecanismo de señalización y el mutex es un mecanismo de bloqueo, pero el semáforo binario parece funcionar como un mutex que crea confusión, pero ambos son conceptos diferentes adecuados para diferentes tipos de trabajo.

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.