¿Por qué pude exceder el máximo de ‘Preguntar para responder’?

Ese es el resultado de lo que se llama una “condición de carrera”, lo que significa que la operación que se realiza depende de las cosas que suceden en una secuencia particular, pero que la secuencia no está garantizada debido a la capacidad de otra operación de competir y romper la secuencia. En otras palabras, es posible que algo inesperado interrumpa la secuencia esperada de operaciones.

Cada vez que “pide una respuesta”, el software debe verificar que no se haya excedido el recuento máximo, realizar la operación “pedir respuesta”, incrementar el recuento de preguntas y guardar el recuento. Tan pronto como el software haya confirmado que no se ha excedido el máximo, comienza la carrera. La carrera finaliza cuando el recuento incrementado ha sido almacenado (y replicado, en un sistema distribuido).

El software puede verificar si se ha excedido el máximo, luego realizar la operación “preguntar para responder” y luego aumentar la cantidad de veces que ha preguntado. Si ese es el caso, hay una ventana de oportunidad relativamente grande para explotar la condición de la carrera. Esa ventana podría reducirse incrementando y almacenando el conteo inmediatamente después de la verificación, pero la condición de la carrera aún se mantendría; Incrementar y almacenar lleva tiempo. Aún así, reducir la duración de la condición de carrera es un paso importante. A veces es incluso “lo suficientemente bueno”.

Para evitar la condición de carrera, se podría agregar al software una operación atómica (ininterrumpida) de “si está por debajo del máximo, incrementar y almacenar”. Si esa operación tiene éxito, el software puede “pedir una respuesta” y la condición de carrera ya se ha evitado: la carrera comenzó y terminó dentro de la operación atómica única. Sin embargo, una operación atómica requiere algún tipo de sincronización, y con un sistema distribuido (donde cada operación puede ejecutarse en un servidor diferente), dicha sincronización puede presentar problemas de rendimiento. Eso podría evitarse haciendo un control atómico e incremento en el cliente (en la aplicación) en este caso. Sin embargo, eso tiene los inconvenientes de dejar el servicio web explotable y requerir que todos los clientes (incluida la interfaz del navegador web) implementen la verificación.

Si es razonable aislar una sesión de usuario en un solo servidor, la operación atómica se puede realizar en ese servidor sin sincronizar con otros servidores. Aún sería posible explotar la condición de la carrera mediante el uso de múltiples sesiones, pero eso no sería probable que ocurriera por accidente. Esa solución probablemente sería “lo suficientemente buena”. Si pudiera aislar las operaciones de verificación e incremento para un usuario determinado (independientemente de la sesión) en un solo servidor, eso resolvería completamente la condición de la carrera.