Respuestas:
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" .
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é.
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.
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?
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.
Un semáforo es un mecanismo de sincronización de conteo, un mutex no lo es.
Esta pregunta tiene respuestas relevantes y un enlace a la guía oficial de Java: ¿Hay un mutex en Java?
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 unorelease()
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:
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.
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.
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.
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.
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.
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.