← SEARCHABLE ARCHIVE
Operating System · 2026-07-15

Sincronización de subprocesos y condiciones de carrera.

¿Por qué los resultados de los datos compartidos cambian cada vez que los ejecuto?

INTERACTIVE READING MODE →

Los artículos escritos en este blog fueron creados con el objetivo de enseñar. Además, la información del artículo puede ser incorrecta, así que tenga cuidado.

Los subprocesos del mismo proceso comparten datos globales y de montón. Gracias a esto se pueden intercambiar datos rápidamente, pero si se lee y escribe el mismo valor simultáneamente, los resultados pueden variar cada vez que se ejecuta.

Este problema se llama condición de carrera.

count++ no es una operación única

int count = 0;

void AddCount()
{
    ++count;
}

Puede ser una línea de código, pero en la CPU pueden ser varios pasos: leer un valor, sumar 1 y almacenarlo nuevamente.

El hilo A lee el recuento 0
El hilo B lee el conteo 0
El hilo A almacena 1
El hilo B almacena 1

Lo incrementamos dos veces, pero el resultado final es 1, no 2. Dado que el orden de ejecución de los subprocesos varía según la situación del sistema operativo, este puede ser un error que aparece sólo ocasionalmente durante las pruebas.

Mutex permite que solo entre un hilo a la vez

std::mutex countMutex;
int count = 0;

void AddCount()
{
    std::lock_guard<std::mutex> lock(countMutex);
    ++count;
}

Mientras el hilo que bloqueó el mutex ejecuta la sección crítica, otros hilos esperan. lock_guardSi usa , el bloqueo se libera automáticamente incluso cuando finaliza la función o se produce una excepción.

Atomic se puede utilizar para valores simples.

Las operaciones atómicas se pueden utilizar para operaciones pequeñas, como aumentar un número entero.

std::atomic<int> count = 0;

void AddCount()
{
    ++count;
}

Sin embargo, si es necesario mantener de forma segura las relaciones entre múltiples variables al mismo tiempo, no se puede resolver con un solo átomo. Por ejemplo, si la deducción de oro y la adición de artículos deben realizarse juntas, ambas deben estar protegidas por una única área crítica.

También debes tener cuidado con los puntos muertos.

Si dos subprocesos esperan un bloqueo retenido por el otro, nadie puede continuar. Esto se llama punto muerto.

Hilo A: Mantiene el bloqueo 1 y espera el bloqueo 2
Hilo B: Mantiene el bloqueo 2 y espera el bloqueo 1

Debe adquirir el hábito de adquirir siempre los candados en el mismo orden y no realizar tareas prolongadas mientras sostiene el candado.

El objetivo del subproceso múltiple no es crear muchos subprocesos. Reduzca los datos compartidos, defina claramente el alcance de lo que se debe compartir y utilice una herramienta de sincronización que se ajuste a ese alcance.