Coordinación segura de acceso a recursos compartidos
Comenzar arrow_downwardCuando múltiples threads acceden a los mismos datos, pueden ocurrir problemas.
Sección crítica: código que accede a recursos compartidos y debe ejecutarse de forma atómica.
Primitivas de sincronización: semáforos, mutexes y colas de mensajes.
Avanza paso a paso y observa cómo la misma secuencia de operaciones produce resultados distintos con y sin mutex.
Ejemplo práctico: dos contadores que siempre deben sumar 40.
Mecanismo de conteo para gestionar acceso a recursos finitos.
Un semáforo mantiene un contador interno que representa el número de recursos disponibles.
k_sem_give(): incrementa contador (thread o ISR)
k_sem_take(): decrementa, bloquea si es 0
k_sem_give() siempre permitido. k_sem_take() solo con K_NO_WAIT (nunca bloquear en ISR).
Patrón productor-consumidor con semáforos.
initial = limit
Limitar acceso concurrente
initial=0, limit=1
Señalización/gate
Exclusión mutua para proteger secciones críticas.
Un mutex (Mutual Exclusion) es un candado binario: bloqueado o desbloqueado.
k_mutex_lock(): adquirir, bloquea si ocupado
k_mutex_unlock(): liberar (solo dueño)
Protegiendo una sección crítica con mutex.
k_mutex_lock() mientras ya tiene el mutex, incrementa un contador interno y no se bloquea.
increment_count + decrement_count = 40 siempre se mantiene visible para otros threads.
Diferencias clave entre ambas primitivas.
| Aspecto |
flag
Semáforo
|
lock
Mutex
|
|---|---|---|
| Uso típico | Contar recursos disponibles | Proteger sección crítica |
| Propiedad | cualquiera puede give/take | solo dueño unlock |
| Desde ISR | give siempre, take con K_NO_WAIT | nunca |
| Herencia de prioridad | ||
| Valor inicial | 0 a límite (configurable) | Siempre desbloqueado |
| Bloqueo recursivo |
Guía rápida para elegir la primitiva correcta.
¿Cómo evitar que threads de baja prioridad bloqueen a los de alta?
Alternativa thread-safe para pasar datos entre threads.
Una cola FIFO para enviar mensajes de tamaño fijo entre threads. Evita la necesidad de variables compartidas.
k_msgq_put(): añadir mensaje a la cola
k_msgq_get(): recibir mensaje de la cola
Definición y uso de una cola de mensajes para datos de sensor.
Consejos para evitar problemas comunes.
Minimiza el tiempo dentro de la sección crítica. Otros threads están esperando.
Libera los locks incluso en paths de error. Usa patrones como goto cleanup.
Múltiples locks aumentan el riesgo de deadlock. Si es necesario, siempre en el mismo orden.
Usa mutex cuando proteges estructuras de datos compartidas.
Usa semáforo para contar recursos o señalizar eventos.
Usa colas de mensajes para transferir datos entre threads.
Un deadlock ocurre cuando dos threads esperan mutuamente por recursos que el otro tiene.
Conceptos fundamentales de sincronización en Zephyr.
Ocurren cuando threads acceden a datos compartidos sin sincronización
Conteo de recursos. Sin propiedad. Usables desde ISR
Exclusión mutua. Con propiedad y herencia de prioridad
Paso de datos thread-safe. Evita variables compartidas
Evita inversión de prioridad. Solo en mutexes
Minimiza tiempo en sección crítica. Siempre libera locks
"La sincronización correcta es esencial para sistemas multithreading fiables."
Elige la primitiva adecuada: mutex para proteger datos, semáforo para contar, cola para transferir.
Exploraremos características avanzadas de Zephyr: timers, eventos, y gestión de energía.