(Тот факт, что русского перевода понятию «lock-free» в литературе ещё не устоялось, — нисколько меня не убеждает, что такого перевода не должно быть.)
Предположим, анализ производительности вашего приложения выявил, что существенная часть процессорного времени тратится в некой вычислительной функции, и более того, эта функция многократно вызывается с одними и теми же параметрами — выполняя одинаковые вычисления вновь и вновь. Напрашивается простая оптимизация — кэш из одной записи, в котором бы хранились исходные данные и результат последнего вычисления.
Само собой, этот код потоконебезопасен: если один поток находится внутри вызова
Простое решение — заключить код в критическую секцию; но простота идёт в ущерб производительности: если, скажем,
Посмотрим, как можно реализовать наш кэш беззамочно.
Предположим, анализ производительности вашего приложения выявил, что существенная часть процессорного времени тратится в некой вычислительной функции, и более того, эта функция многократно вызывается с одними и теми же параметрами — выполняя одинаковые вычисления вновь и вновь. Напрашивается простая оптимизация — кэш из одной записи, в котором бы хранились исходные данные и результат последнего вычисления.
BOOL IsPrime(int n) { static int nLast = 1; static BOOL fLastIsPrime = FALSE; // если значение параметра не изменилось с прошлого раза, // воспользуемся готовым результатом if (n == nLast) return fLastIsPrime; // вычислим и запомним новый результат nLast = n; fLastIsPrime = slow_IsPrime(n); return fLastIsPrime; }
Само собой, этот код потоконебезопасен: если один поток находится внутри вызова
slow_IsPrime()
, то другой поток, вызвавший IsPrime()
, застанет значения переменных nLast
и fLastIsPrime
несоответствующими одно другому.Простое решение — заключить код в критическую секцию; но простота идёт в ущерб производительности: если, скажем,
nLast
= 5, fLastIsPrime
= TRUE, и два потока одновременно вызывают IsPrime(5)
, то совершенно ни к чему им выстраиваться в очередь: ничего не мешает им одновременно воспользоваться кэшированным значением.Посмотрим, как можно реализовать наш кэш беззамочно.