Imagine que estaba escribiendo una aplicación bancaria, y su aplicación tenía una solicitud para retirar diez libras (sí, soy inglés;)) de la cuenta. Por lo tanto, debe leer el saldo de la cuenta corriente en una variable local, restar el retiro y luego escribir de nuevo el saldo en la memoria.
Sin embargo, ¿qué pasa si ocurre otra solicitud concurrente entre que usted lee el valor y lo escribe? Existe la posibilidad de que el resultado de esa solicitud sea sobrescrito por completo por el primero, y el saldo de la cuenta sea incorrecto.
Test-and-set nos ayuda a solucionar ese problema comprobando que el valor que sobrescribe es el que usted cree que debería ser. En este caso, puede verificar que el saldo sea el valor original que haya leído. Como es atómico, no se puede interrumpir, por lo que nadie puede tirar de la alfombra debajo de usted entre la lectura y la escritura.
Otra forma de solucionar el mismo problema es eliminar un bloqueo en la ubicación de la memoria. Desafortunadamente, los bloqueos son tremendamente difíciles de acertar, difíciles de razonar, tienen problemas de escalabilidad y se comportan mal frente a fallas, por lo que no son una solución ideal (pero definitivamente práctica). Los enfoques de prueba y configuración forman la base de algunas Memorias transaccionales de software, que optimísticamente permiten que cada transacción se ejecute al mismo tiempo, a costa de deshacerse de todas ellas si entran en conflicto.
+1 Me acabas de ayudar a resolver un problema en el que estaba trabajando. –
@ jason-cohen: Esa es en realidad una descripción de [Compare and Swap] (https://en.wikipedia.org/wiki/Compare-and-swap). La prueba y el conjunto implican solo los valores 0 y 1. La parte ** set ** se refiere a establecer el valor en una ubicación de memoria especificada en 1. Devuelve el valor anterior, ya sea un 1 o un 0, y hace todo esto en una sola operación atómica. –
@GregSlepak es correcto, esto es compare_and_swap. test_and_set() toma un puntero booleano a un objetivo, lo establece en TRUE y devuelve el valor original del puntero. Si el valor de retorno de test_and_set (& lock) (es decir, el valor original de & lock) es verdadero, entonces ingresamos a la sección crítica. – mateor