mutex - semaforos - ¿Cuáles son los usos prácticos de los semáforos?
que es exclusión mutua informatica (6)
Citando a Doug Schmidt en http://www.cs.wustl.edu/~schmidt/win32-cv-1.html sección 2.2:
Los semáforos de conteo son un mecanismo de sincronización comúnmente utilizado para serializar o coordinar múltiples hilos de control. Conceptualmente, los semáforos de conteo son enteros no negativos que pueden incrementarse y disminuirse atómicamente. Si un hilo intenta disminuir un semáforo cuyo valor es igual a 0, este hilo se suspende a la espera de que otro hilo incremente el conteo de semáforos por encima de 0.
Los semáforos de conteo se utilizan a menudo para realizar un seguimiento de los cambios en el estado de los objetos compartidos por varios subprocesos en un proceso. Por ejemplo, pueden registrar la ocurrencia de un evento en particular. A diferencia de las variables condicionales, los semáforos mantienen el estado. Por lo tanto, permiten que los hilos tomen decisiones basadas en este estado, incluso si el evento ha ocurrido en el pasado.
En cuanto a los patrones, hay dos según reference
Los semáforos de conteo se usan típicamente para dos cosas:
Contando los eventos. En este escenario de uso, un controlador de eventos ''dará'' un semáforo cada vez que ocurra un evento (incrementando el valor de conteo del semáforo), y una tarea de controlador ''tomará'' un semáforo cada vez que procese un evento (disminuyendo el valor del número de semáforos). El valor de conteo es, por lo tanto, la diferencia entre el número de eventos que han ocurrido y el número que se ha procesado. En este caso, es deseable que el valor de conteo sea cero cuando se crea el semáforo.
Administracion de recursos. En este escenario de uso, el valor de conteo indica la cantidad de recursos disponibles. Para obtener el control de un recurso, una tarea primero debe obtener un semáforo: disminuir el valor de conteo del semáforo. Cuando el valor de conteo llega a cero, no hay recursos libres. Cuando una tarea finaliza con el recurso, ''devuelve'' el semáforo atrás, incrementando el valor del recuento de semáforo. En este caso, es deseable que el valor de conteo sea igual al valor de conteo máximo cuando se crea el semáforo.
Los no binarios ..
Nunca he encontrado un problema que requiera que use un semáforo en lugar de un mutex. Entonces, ¿este constructo en su mayoría teórico, o de verdad, como Office, Firefox, tiene lugares donde lo usa? Si es así, ¿cuáles son los patrones de uso comunes para los semáforos?
Creo que ya sabes lo que es un semáforo y te estás preguntando cómo se usa en "software real".
"en realidad como Office, Firefox tiene lugares donde lo usan?"
Sí, el "software real" usa mucho los semáforos, no es solo teórico, por ejemplo , la fuente de Chromium, el código de manejo de semáforos de Windows y el mismo código utilizado por Virtual Box .
"¿Cuáles son los usos prácticos de los semáforos" / "¿Cuáles son los patrones de uso comunes para los semáforos?"
Son más adecuados para problemas de sincronización productor-consumidor. Situaciones que tiene el número de productores y consumidores tanto > 1.
La reference del uso típico de semáforos por parte del Fuhrmanator es buena.
He usado un semáforo en un entorno de producción varias veces. Tenga un servicio de Windows en ejecución que obtendrá una lista de tareas a realizar. Todas estas tareas pueden ejecutarse en paralelo. Así que inicialmente solo los dejamos todos en un .net Threadpool y los configuramos para que se ejecuten.
Después de un corto período surgió un problema. El trabajo realizado en paralelo también estaba utilizando la agrupación de hilos. Por lo tanto, si comenzamos demasiadas tareas en el grupo de subprocesos, consumirían todo el grupo y luego esperarían a que su tarea en la cola obtuviera un espacio en el grupo de subprocesos.
La solución con fugas era simplemente mantener un contador compartido donde las tareas lo incrementarían y disminuirían a medida que se siguieran ejecutando. Eso funcionó por un tiempo, pero eventualmente el servicio dejaría de hacer cualquier cosa. Las condiciones de carrera repetidas dieron como resultado que el contador mostrara que todas las ranuras permitidas en el conjunto de hilos se tomaron aunque no se estuviera ejecutando nada.
Al final un semáforo resolvió el problema.
Los semáforos no binarios se utilizan en la asignación de recursos. Un semáforo puede contar el número de un recurso en particular.
Si tiene un conjunto de conexiones, como un navegador web, entonces un hilo individual puede reservar un miembro del conjunto al esperar en el semáforo para obtener una conexión, utiliza la conexión y luego libera la conexión liberando el semáforo.
Puede emular un semáforo creando un contador y luego estableciendo una región de exclusión mutua alrededor del contador. Sin embargo, esperar por un recurso como el anterior, requiere un mutex de dos niveles y no es tan elegante como usar el semáforo.
Un posible ejemplo práctico podría ser un grupo de subprocesos fijo: no desea desperdiciar todos los recursos del sistema, por lo que permite que solo se ejecute un cierto número de subprocesos en un momento determinado; todos los subprocesos restantes esperarán en una cola.
Ahora, dudo que, por ejemplo, Java Thread Pool se implementen usando un recurso simple como un semáforo, pero cualquiera que sea la construcción de sincronización que se use, es teóricamente equivalente. Puede obtener una explicación completa sobre los grupos de subprocesos de Java (y los grupos de subprocesos fijos) aquí: http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
Un semáforo puede contar. El conteo es fundamentalmente inseguro de subprocesos, es una operación de lectura-modificación-escritura en el procesador y, por lo tanto, no es atómico . Existen primitivas menores disponibles para contar de forma segura, el Enclavamiento.Incremento () es atómico. Pero la atomicidad es un primitivo de subprocesamiento bastante débil, en muchos casos también debe bloquear el código cuando el conteo se encuentra en un valor crítico.
Con 0 siendo "crítico", todos los recursos han sido utilizados. Un ejemplo estándar es la cuenta regresiva de los núcleos del procesador para ejecutar subprocesos, una vez que los haya utilizado todos, entonces no debe iniciar otro subproceso hasta que uno de ellos se complete y ya no necesite un núcleo de procesador. Tan básico como se pone.
Los semáforos binarios a menudo aparecen en la literatura sobre el enhebrado. Una entrada de libro de texto estándar y estrechamente vinculada a un compañero holandés llamado Edsger Dijkstra. Un pionero en ciencias de la computación que comenzó a pensar en la década de 1960 sobre qué haría usted para conseguir que un procesador ejecute varios programas. Su anotación P y V solo tiene sentido para un hablante holandés como yo. Parkeer y Vrij son términos que usa cuando intenta poner su auto en algún lugar :) Esto fue mucho antes de que todos comenzaran a pensar en tener diferentes tipos de primitivas de enhebrado, como mutex y monitor. Primitivas que solo requieren tener soporte para un semáforo, una vez que tienes un semáforo binario, haces todo lo demás. Construyendo abstracciones sobre una instalación básica, la forma en que la composición funciona en software.
Empujando un poco, estoy en una buena racha, una cosa que hace que Semaphore sea bastante diferente de otras primitivas como Mutex y Monitor y el bloqueo es que no tiene afinidad con los hilos. Eso es algo bastante importante cuando escribe código en subprocesos, el contrato habitual que intenta implementar es que solo un subproceso puede acceder a un recurso al mismo tiempo. Todos los demás objetos de sincronización de .NET son reingresantes , no puede interrumpirse al bloquear un bloqueo más de una vez en el mismo hilo. Son muy amigables y simplemente incrementan un contador cuando adquieres el candado. Y cuenta de nuevo cuando sueltes. Y solo renunciar al bloqueo cuando el conteo llegue a 0. El semáforo no funciona de esa manera, cuenta cuando adquiere independientemente del hilo que lo haya adquirido. En algunos casos, eso realmente importa, como el ejemplo de cuenta regresiva del hilo que mencioné anteriormente.
Que es realmente lo que es útil para. No es exactamente muy común. Un monitor es la navaja suiza de roscado, por lo que tiene su propia palabra clave. La palabra clave de bloqueo en C #, SyncLock en VB.NET