2009-10-06 25 views
31

Tengo una clase que tiene un estado (una enumeración simple) y que se accede desde dos hilos. Para cambiar el estado, uso un mutex (boost :: mutex). ¿Es seguro verificar el estado (por ejemplo, comparar state_ == ESTABLISHED) o tengo que usar el mutex también en este caso? En otras palabras, ¿necesito el mutex cuando solo quiero leer una variable que podría ser escrita simultáneamente por otro hilo?¿Necesito un mutex para leer?

Respuesta

3

Sí. Si el hilo a lee una variable mientras el hilo b le escribe, puede leer un valor indefinido. La operación de lectura y escritura no es atómica, especialmente en un sistema multiprocesador.

+0

mientras que un hilo de escritura lo hace (fetch-> write-> store) No veo cuando en medio de esos un lector podría obtener un valor indefinido, ya sea el anterior o posterior, pero nunca indefinido. –

+0

Teniendo en cuenta los valores enum que se leen en una instrucción. –

+1

@Arkaitz: undefined probablemente no era la palabra correcta. Pero las arquitecturas de CPU/memoria se vuelven cada vez más complejas con niveles adicionales de cachés, latencias incrementadas, etc. La respuesta es simple: ¡Di no! para bloquear el intercambio de datos. Incluso los expertos cometen muchos errores en esta área. – sellibitze

0

Hablando en general, no, si su variable se declara con "volátil". Y SOLAMENTE si se trata de una sola variable, de lo contrario deberías tener mucho cuidado con posibles carreras.

+0

¿Por qué crees que las materias volátiles? – jalf

+1

@jalf: volátil le dice al compilador que no realice optimizaciones que puedan hacer que su código vea una copia obsoleta de la variable. –

+2

Pero la pregunta no era sobre copias obsoletas. Incluso si la variable no es volátil, se escribirá tarde o temprano. Será atómico independientemente de la volatilidad, y volátil no impide la reordenación de carga/almacenamiento. Así que volátil realmente no te compra nada en este caso. No resuelve el problema que necesita solución, y resuelve uno que se habría resuelto de todos modos. – jalf

0

El acceso a la enumeración (lectura o escritura) debe protegerse.

Otra cosa: Si la contención del hilo es menor y los hilos pertenecen al mismo proceso, entonces la sección crítica sería mejor que el mutex.

8

Tiene dos hilos, intercambian información, sí necesita un mutex y probablemente también necesite una espera condicional.

En su ejemplo (compare state_ == ESTABLISHED) indica que el subproceso # 2 está esperando que el subproceso n. ° 1 inicie una conexión/estado. Sin un mutex o condicionales/eventos, el hilo # 2 tiene que sondear el estado continuamente.

Hilos se utiliza para aumentar el rendimiento (o mejorar la capacidad de respuesta), la votación normalmente resulta en una disminución del rendimiento, ya sea mediante el consumo de una gran cantidad de CPU o introduciendo latencey debido al intervalo de sondeo.

+0

+1 por sugerir variables condicionales. Por los sonidos que tiene, tiene un hilo que necesita responder a un cambio de estado por otro cambio. Si ese es el caso, las variables condicionales son mucho más apropiadas. – Falaina

+0

@Ermelli aún necesitamos mutex si queremos usar busy wait loop de todos modos (porque el bucle puede hacer otra cosa mientras tanto) – Nick

0

En realidad, no hay ninguna razón para bloquear el acceso al objeto para leer. solo quiere bloquearlo mientras escribe en él. esto es exactamente lo que es un bloqueo lector-escritor. no bloquea el objeto mientras no haya operaciones de escritura. mejora el rendimiento y evita los bloqueos. consulte los siguientes enlaces para explicaciones más elaboradas:

wikipedia codeproject

12

Depende.

El lenguaje C++ no dice nada sobre los hilos o la atomicidad.

Pero en la mayoría moderna CPU, la lectura de un número entero es una operación atómica, lo que significa que siempre va a leer un valor constante, incluso sin un mutex.

Sin embargo, sin exclusión mutua, o alguna otra forma de sincronización, el compilador y la CPU son libres de cambiar el orden de lectura y escritura, así que cualquier cosa más compleja, cualquier cosa que implica acceder a múltiples variables, es todavía inseguro en el caso general.

Suponiendo que el subproceso de escritura actualiza algunos datos, y luego establece un indicador entero para informar a otros hilos que se dispone de datos, esto podría ser reordenados por lo que el indicador se establece antes de la actualización de los datos. A menos que use un mutex u otra forma de barrera de memoria.

Así que si quiere un comportamiento correcto, no necesita un mutex como tal, y no hay problema si otro hilo escribe en la variable mientras lo está leyendo. Será atómico a menos que estés trabajando en una CPU muy inusual.Pero usted do necesita una barrera de memoria de algún tipo para evitar el reordenamiento en el compilador o la CPU.

+0

A menos que especifique un volátil, la lectura (o la escritura) podría * nunca * realizarse. Tarde o temprano no es lo suficientemente bueno. – EFraim

+3

Pero incluso con volátiles, la CPU o el compilador podrían reordenar las escrituras, dejándolas sin sentido. La solución correcta es una barrera de memoria, y luego volátil es solo una desoptimización innecesaria. – jalf

+0

@jalf: No, si solo necesita una sola bandera. Lee la pregunta nuevamente – EFraim