Почему код майнинга биткойнов имеет один и тот же оператор if дважды?

Из источника v0.9.3 miner.cpp ( https://github.com/bitcoin/bitcoin/blob/v0.9.3/src/miner.cpp#L598-L604 ):

if (GetTimeMillis() - nHPSTimerStart > 4000)
{
    static CCriticalSection cs;
    {
        LOCK(cs);
        if (GetTimeMillis() - nHPSTimerStart > 4000)
        {
        ....

Почему один и тот же оператор if " if (GetTimeMillis() - nHPSTimerStart > 4000)" выполняется дважды? GetTimeMillis() может только увеличиваться, поэтому кажется, что если первое истинно, то второе утверждение также может быть оценено только как истинное и бесполезно. Я предполагаю, что это не совсем правильно, и я также предполагаю, что это как-то связано с CCriticalSelection, но хотел бы лучше понять его природу.

Спасибо!

Я согласен, я думаю, что это ошибка копирования-вставки. Возможно, вам стоит попросить #bitcoin-devперепроверить.
Может ли какой-либо другой поток изменить nHPSTimerStart?
Да, я так думаю. Над майнингом может работать довольно много потоков.
Я использовал что-то подобное раньше. Первый ifпроверяет, стоит ли нам делать потенциально дорогостоящую блокировку. Если да, то мы блокируем, и теперь это nHPSTimerStartгарантированно не изменится, и мы можем безопасно выполнить ifснова.
Спасибо, Флорис, это кажется разумным. Если вы опубликуете как ответ, я могу пометить его как таковой.

Ответы (1)

Это блокировка с двойной проверкой , т.е.

... шаблон проектирования программного обеспечения, используемый для уменьшения накладных расходов на получение блокировки путем первой проверки критерия блокировки [...] без фактического получения блокировки.

Этот шаблон может быть чреват проблемами; даже люди, которые иначе знают, что они делают, могут быть укушены тонкими проблемами. См., например, C++ and the Perils of Double-Checked Locking Скотта Мейерса и Андрея Александреску.

Однако конкретный вариант использования, который вы цитируете, выглядит довольно безобидным.