/* Page prose (es) */
"HardToCatch" = "# Por qué es tan difícil de atrapar\n\nLa corrupción depende del *momento*: qué cajero da la casualidad de que lee durante el hueco de otro. El momento cambia con la carga de la CPU, el número de núcleos, qué más está haciendo el dispositivo, y pura suerte. Eso es lo que significa **no determinista**: el mismo código, las mismas entradas, resultados distintos. Así que el error:\n\n* **Puede que no se reproduzca.** Pasó tus pruebas porque tus pruebas tuvieron suerte.\n* **Puede desaparecer bajo un depurador,** que cambia el momento.\n* **Puede que solo muerda en producción,** en un dispositivo más ocupado o más lento que el tuyo.\n\nNo puedes fiarte de ejecutarlo para encontrarlo. Lo encuentras *leyéndolo*. La única pregunta que importa:\n\n**¿Hay estado que se comparte entre tareas concurrentes, y se muta, sin que nada coordine el acceso?**\n\nEn el ejemplo: `account.balance` se comparte (una `Account`, capturada por cada clausura), se muta (`account.balance = updated`), y nada coordina la cola concurrente `tellers`. Tres de tres: eso es una carrera de datos, demostrable sobre el papel, sin necesidad de ejecutar ninguna prueba.\n\n* callout(Nota al margen): En un proyecto completo de Xcode hay una herramienta llamada **Thread Sanitizer** que señala las carreras de datos en tiempo de ejecución. Es solo de Xcode, no la tendrás en Swift Playground, así que a lo largo de este libro aprendes a deducir las carreras a mano, que de todos modos es la habilidad más duradera.\n\n[Anterior](@previous)  |  página 3 de 9  |  [Siguiente: La solución con cola serial](@next)";
