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.
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.
¿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.
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.
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
... 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 ...
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á .
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).
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.
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:
Bloquear
Usar sección crítica
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:
wait (s) // inicialmente el valor es uno después de llamar a wait su valor disminuyó en uno, es decir, 0
Usar sección crítica
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.
En Windows, hay dos diferencias entre mutexes y semáforos binarios:
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.
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á.
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".
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
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.
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.
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.
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.
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.
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.
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 .
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.
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.
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.
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.
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.
Un proceso no puede salir mientras se mantiene un mutex.
Un mutex no puede ser adquirido por un controlador de interrupciones o la mitad inferior, incluso con mutex_trylock ().
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
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.
Respuestas:
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:
Aquí hay un ejemplo simple:
Semáforo binario El semáforo
binario aborda una pregunta totalmente diferente:
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.
fuente
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.
fuente
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 principalEl ejemplo del inodoro es una analogía agradable:
fuente
Buenos artículos sobre el tema:
De la parte 2:
fuente
Como ninguna de las respuestas anteriores aclara la confusión, aquí hay una que despejó mi confusión.
Fuente: http://www.geeksforgeeks.org/mutex-vs-semaphore/
fuente
Su semántica de sincronización es muy diferente:
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).
fuente
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:
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í:
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.
fuente
futex
llamada 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.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.
fuente
Mutex: Supongamos que tenemos una sección crítica que el hilo T1 quiere acceder, luego sigue los siguientes pasos. T1:
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:
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.
fuente
En Windows, hay dos diferencias entre mutexes y semáforos binarios:
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.
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á.
fuente
Obviamente, usa mutex para bloquear datos en un hilo al que otro hilo accede al mismo tiempo. Asume que acabas de llamar
lock()
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!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".
fuente
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"
fuente
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
fuente
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.
fuente
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.
fuente
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.
fuente
Mutex trabaja en el bloqueo de la región crítica, pero Semaphore trabaja en la cuenta.
fuente
http://www.geeksforgeeks.org/archives/9102 discute en detalles.
Mutex
es un mecanismo de bloqueo utilizado para sincronizar el acceso a un recurso.Semaphore
Es un mecanismo de señalización.Depende del programador si él / ella quiere usar el semáforo binario en lugar de mutex.
fuente
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.
fuente
sem_post()
paraSCHED_FIFO
ySCHED_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.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.
fuente
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:
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
EDEADLK
si intentas bloquear el mismo dos veces yEPERM
si desbloqueas un mutex que no es tuyo.Una vez inicializado, podemos colocar estos controles en nuestro código de esta manera:
fuente
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.
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.
fuente
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.
fuente
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 .
fuente
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.
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.
fuente
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 .
fuente
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.
fuente
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.
fuente
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] Desarrollo del kernel de Linux, tercera edición Robert Love
fuente
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.
fuente