¿Qué es mutex y semáforo en Java? ¿Cual es la diferencia principal?

Respuestas:

115

El semáforo se puede contar, mientras que el mutex solo puede contar hasta 1.

Suponga que tiene un hilo en ejecución que acepta conexiones de cliente. Este hilo puede manejar 10 clientes simultáneamente. Luego, cada nuevo cliente establece el semáforo hasta que llega a 10. Cuando el semáforo tiene 10 banderas, entonces su hilo no aceptará nuevas conexiones

Los mutex se utilizan generalmente para proteger cosas. Suponga que sus 10 clientes pueden acceder a múltiples partes del sistema. Luego, puede proteger una parte del sistema con un mutex para que cuando 1 cliente esté conectado a ese subsistema, nadie más deba tener acceso. También puede utilizar un semáforo para este propósito. Un mutex es un "semáforo de exclusión mutua" .

Eric
fuente
4
Esto no es completamente cierto. El mismo hilo puede ingresar al mismo mutex más de una vez, por lo que es necesario mantener un recuento para garantizar que las entradas y salidas estén equilibradas.
finnw
1
@finnw, en general hay dos tipos de mutex, recursivos y no recursivos. ¿Java utiliza de forma predeterminada el tipo recursivo?
edA-qa mort-ora-y
2
@ edA-qa mort-ora-y, el término "Mutex" no se usa en la especificación Java VM o API, por lo que supongo que se refiere al monitor integrado en cada objeto, que también es similar al objeto Win32 llamado Mutex . Lo mismo se aplica a a ReentrantLock. Todos estos son recursivos. No tengo conocimiento de ningún ejemplo del "mundo real" de exclusión mutua no recursiva (solo los he visto en libros de texto), así que no los consideré.
finnw
2
Las exclusiones mutuas no recursivas se pueden implementar utilizando un semáforo con cuenta uno. Esto puede resultar útil si desea evitar llamadas recursivas. Esto tiene usos prácticos, personalmente lo he usado en grandes proyectos para detectar bucles en el código de inicialización (A inicializa B que intenta inicializar A nuevamente).
Alexander Torstling
1
En el estándar C ++ 11 (C ++ 0x), mutex no es recursivo. También proporcionan un 'recursive_mutex' separado para aquellos que lo necesitan. Sé que estamos hablando de Java aquí, pero muchos de nosotros codificamos en varios idiomas ahora.
Aditya Kumar Pandey
139

Desafortunadamente, todos han pasado por alto la diferencia más importante entre el semáforo y el mutex; el concepto de " propiedad ".

Los semáforos no tienen noción de propiedad, esto significa que cualquier hilo puede liberar un semáforo (esto puede generar muchos problemas en sí mismo, pero puede ayudar con la "detección de muerte"). Mientras que un mutex tiene el concepto de propiedad (es decir, solo puede liberar un mutex que haya adquirido).
La propiedad es increíblemente importante para la programación segura de sistemas concurrentes. Siempre recomendaría usar mutex en lugar de un semáforo (pero hay implicaciones de rendimiento).

Los mutex también pueden admitir herencia de prioridad (que puede ayudar con el problema de inversión de prioridad) y recursividad (eliminando un tipo de interbloqueo).

También debe señalarse que hay semáforos "binarios" y semáforos "contadores / generales". El semáforo de Java es un semáforo de conteo y, por lo tanto, permite que se inicialice con un valor mayor que uno (mientras que, como se señaló, un mutex solo puede contar conceptual de uno). La utilidad de esto se ha señalado en otras publicaciones.

Entonces, para resumir, a menos que tenga múltiples recursos para administrar, siempre recomendaría el mutex sobre el semáforo.

feabhas
fuente
1
La respuesta de Feabhas es bastante importante: el mutex comprueba que el hilo que intenta liberar el mutex realmente lo posee. He tenido esto como una pregunta de entrevista, así que vale la pena intentar recordarlo.
Andrew Paté
40

Mutex es básicamente exclusión mutua. Solo un hilo puede adquirir el recurso a la vez. Cuando un subproceso adquiere el recurso, ningún otro subproceso puede adquirir el recurso hasta que se libera el subproceso propietario del recurso. Todos los subprocesos que esperan adquirir recursos se bloquearán.

Semaphore se utiliza para controlar el número de subprocesos que se ejecutan. Habrá un conjunto fijo de recursos. El recuento de recursos se reducirá cada vez que un hilo posea el mismo. Cuando el recuento de semáforos llega a 0, no se permite que otros subprocesos adquieran el recurso. Los subprocesos se bloquean hasta que otros subprocesos que poseen liberaciones de recursos.

En resumen, la principal diferencia es ¿cuántos subprocesos pueden adquirir el recurso a la vez?

  • Mutex: es UNO.
  • Semáforo - su DEFINED_COUNT, (tantos como recuento de semáforos)
aJ.
fuente
8

Un mutex se utiliza para el acceso en serie a un recurso, mientras que un semáforo limita el acceso a un recurso hasta un número determinado. Puede pensar en un mutex como un semáforo con un recuento de acceso de 1. Independientemente de lo que establezca su recuento de semáforos, esos subprocesos pueden acceder al recurso antes de que se bloquee el recurso.

Jason Coco
fuente
3

Un semáforo es un mecanismo de sincronización de conteo, un mutex no lo es.

Brian Rasmussen
fuente
3

Un mutex se conoce a menudo como semáforo binario. Si bien se puede crear un semáforo con cualquier recuento distinto de cero, un mutex es conceptualmente un semeáforo con un recuento superior de 1.

Sean
fuente
1

Semáforo :

Un semáforo de conteo. Conceptualmente, un semáforo mantiene un conjunto de permisos. Cada uno acquire()bloquea si es necesario hasta que haya un permiso disponible y luego lo toma. Cada uno release()agrega un permiso, lo que potencialmente libera a un adquirente bloqueante. Sin embargo, no se utilizan objetos de permiso reales; el semáforo solo lleva un recuento del número disponible y actúa en consecuencia.

Los semáforos se utilizan a menudo para restringir la cantidad de subprocesos que pueden acceder a algún recurso (físico o lógico)

Java no tiene una API Mutex incorporada. Pero se puede implementar como semáforo binario.

Un semáforo inicializado a uno, y que se utiliza de manera que solo tenga como máximo un permiso disponible, puede servir como bloqueo de exclusión mutua. Esto se conoce más comúnmente como semáforo binario, porque solo tiene dos estados: un permiso disponible o cero permisos disponibles.

Cuando se usa de esta manera, el semáforo binario tiene la propiedad (a diferencia de muchas implementaciones de Lock), que el "bloqueo" puede ser liberado por un hilo que no sea el propietario (ya que los semáforos no tienen noción de propiedad) . Esto puede resultar útil en algunos contextos especializados, como la recuperación de interbloqueo.

Entonces, diferencias clave entre Semaphore y Mutex:

  1. El semáforo restringe el número de subprocesos para acceder a un recurso mediante permisos. Mutex permite que solo un subproceso acceda al recurso.

  2. Ningún hilo posee Semaphore. Los subprocesos pueden actualizar el número de permisos mediante llamadas acquire()y release()métodos. Las exclusiones mutuas solo deben desbloquearse mediante el subproceso que sujeta el bloqueo.

  3. Cuando se usa un mutex con variables de condición, hay un corchete implícito: está claro qué parte del programa se está protegiendo . Este no es necesariamente el caso de un semáforo, que podría llamarse el punto de partida de la programación concurrente ; es poderoso pero demasiado fácil de usar de una manera no estructurada e indeterminada.

Ravindra babu
fuente
0

Mutex es un semáforo binario. Debe inicializarse con 1, de modo que se cumpla el principio de primero en llegar, primero en servirse. Esto nos lleva a la otra propiedad especial de cada mutex: el que bajó , debe ser el que suba . Ergo, hemos obtenido la exclusión mutua sobre algún recurso.

Ahora puede ver que un mutex es un caso especial de semáforo general.

dim8
fuente
0

El objeto de la sincronización SemáforoImplementa un semáforo clásico. Un semáforo controla el acceso a un recurso compartido por un contador. Si el contador es mayor que cero, se concede acceso; Si es cero, se deniega el acceso. El contador cuenta los permisos que permiten el acceso al recurso compartido. Luego, para acceder al recurso, un hilo debe recibir permiso del semáforo. En general, para utilizar un semáforo, el hilo que quiere acceder al recurso compartido intenta adquirir un permiso. Si el conteo de semáforos es mayor que cero, el hilo adquiere un permiso y el conteo de semáforos disminuye. De lo contrario, el hilo se bloquea hasta que pueda obtener un permiso. Cuando el hilo ya no necesita acceder al recurso compartido, libera el permiso, por lo que aumenta el recuento de semáforos. Si hay otro hilo esperando un permiso, adquiere un permiso en ese momento. La clase Semaphore de Java implementa este mecanismo.

Semaphore tiene dos constructores:

Semaphore(int num)
Semaphore(int num, boolean come)

num especifica el recuento inicial del permiso. Luego, num especifica el número de subprocesos que pueden acceder a un recurso compartido en un momento dado. Si num es uno, puede acceder al recurso un hilo a la vez. Al establecer llegado tan cierto, se puede garantizar que los hilos que están esperando se les concede el permiso en el orden que solicitaron.

Amarildo
fuente
0

Comparas lo incomparable, técnicamente no hay diferencia entre un semáforo y un mutex, no tiene sentido. Mutex es solo un nombre significativo como cualquier nombre en la lógica de su aplicación, significa que usted inicializa un semáforo en "1", generalmente se usa para proteger un recurso o una variable protegida para asegurar la exclusión mutua.

Marwen Trabelsi
fuente