Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

204
Views
Cuándo usar un mutex y cuándo no

Tengo una variable global llamada my_list que contiene una lista vinculada (es decir, la variable es un puntero al primer miembro de la lista). Esta variable solo puede ser editada por dos subprocesos, el subproceso A y el subproceso B. En caso de que la lista quede vacía, la variable se establece en NULL . Cuando esto sucede, la variable se establece en NULL primero y luego se libera la memoria.

Como es editado por dos subprocesos, uso un mutex cada vez que el subproceso A o el subproceso B tocan la variable my_list . Nada inusual hasta ahora.

Pero luego viene un tercer hilo, el hilo C. Este hilo nunca tocará la lista enlazada de ninguna manera, pero necesitará saber de vez en cuando si la lista está vacía o no. Entonces, lo único que hará el subproceso C es

 if (my_list) { do_something_completely_unrelated(); }

¿Tengo que usar un mutex para eso? Creo que es una operación atómica, por lo que no se requiere mutex. ¿Es esto correcto?

EDITAR

Agregaré aquí un poco de contexto. La razón por la que me gustaría evitar el uso de un mutex es que la lista se actualiza rara vez (siempre), pero la verificación que proviene del subproceso C ocurre cada pocos milisegundos, por lo que cuantas menos operaciones, mejor.

Si la lista parece no ser NULL , entonces el subproceso C activa una verificación adecuada usando un mutex , y si se confirma que la lista no está vacía, el subproceso C detiene su verificación obsesiva.

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

TL;RD

Según el estándar, es un comportamiento indefinido leer una variable cuando está escrita si al menos una de las operaciones no es atómica.

Respuesta más larga

Desde la sección de comentarios, parece preguntarse si bloqueará su programa o si lo peor que puede pasar es que obtenga el valor incorrecto. Tu comentario, énfasis mío:

Gracias. Pero concretamente ¿qué podría pasar mal? Digamos que la variable es NULL pero el subproceso A la está cambiando en este momento para que se dirija a xxxxxx . El subproceso C intenta leerlo. ¿Qué valor puede obtener? O NULL o xxxxxx , y ambos están bien. ¿Me equivoco al suponer que el programa no fallará?

Diría que esta simple verificación probablemente no hará que su programa se bloquee. La operación de comprobación es segura en el sentido de que lo más probable es que obtenga un valor. El valor puede ser incorrecto, pero lo más probable es que la verificación por sí sola no bloquee su programa.

Sin embargo, ES un comportamiento indefinido:

La ejecución de un programa contiene una carrera de datos si contiene dos acciones en conflicto en diferentes hilos, al menos uno de los cuales no es atómico, y ninguno sucede antes que el otro. Cualquier carrera de datos de este tipo da como resultado un comportamiento indefinido.

Norma C18, apartado 5.1.2.4, párrafo 35

Luego publicaste este comentario de seguimiento:

En realidad, esto no es tan importante, pero ¿estoy en lo cierto al suponer que si el subproceso A está cambiando el valor de NULL a xxxxxx (o viceversa) definitivamente no obtendré yyyyyy , sino NULL o xxxxxx ?

Aquí diría que su suposición es incorrecta. AFIK, no hay nada en el estándar que diga que la asignación de un puntero debe ser una operación atómica, y me sorprendería si lo fuera. Y como mencioné anteriormente, ES un comportamiento indefinido.

Las soluciones sugeridas

Utilice la palabra clave _Atomic

Declare la lista con el calificador _Atomic . Tiene algunas limitaciones. Por ejemplo:

  1. No es una función obligatoria, por lo que podría reducir la portabilidad

  2. No se puede usar con arreglos.

  3. Si se usa con una estructura, los campos de la estructura no se pueden acceder individualmente

2 y 3 no deberían importarle, ya que la lista es solo un indicador.

Lea sobre _Atomic aquí: https://en.cppreference.com/w/c/language/atomic

Usa una copia que no se actualiza en cada acceso

Si _Atomic no es una opción, aquí hay una solución en pseudocódigo:

 if ( now() - lastUpdated > ms ) // If it was more than ms milliseconds since last update lock(myMutex) myListCopy = myList unlock(myMutex) lastUpdated = now() if(myListCopy) do_something_completely_unrelated();

lastUpdated y myListCopy son preferiblemente variables que son locales a la función, pero la parte importante es que el subproceso A y B nunca las toca.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!