: После того, как поток выполняет операцию записи в общую переменную между потоками, результат модификации, вызванный этой операцией записи, может быть успешно прочитан последующей операцией чтения другого потока.
Примечание: Антоним «видимый» еще не видимый, а не невидимый.
означает, что модификация операции записи потока в общей переменной между потоками на данный момент не была прочитана операцией чтения другого потока (и может быть прочитана впоследствии).
:
Этот порядок памяти гарантирует только то, что операции над соответствующей атомарной переменной являются атомарными (без промежуточных состояний). Однако для других потоков результат модификации этой атомарной операции временно находится в состоянии «пока не виден», и дополнительных ограничений, позволяющих избежать такой временной задержки, не существует.
:
Этот порядок памяти будет «упаковывать» результаты модификации всех операций записи, которые происходят до этой операции освобождения в текущем потоке (например, операции присваивания любых других неатомарных переменных или операции Memory_order_relaxed других атомарных переменных и т. д.). Когда другой поток успешно считывает значение, записанное этой операцией освобождения, посредством соответствующей операции получения, результаты модификации этих предыдущих операций записи могут быть детерминированно видимы для этого потока.
:
Этот порядок памяти гарантирует, что все операции чтения, происходящие после этой операции получения в текущем потоке, могут считывать допустимое состояние, полученное при выполнении операции получения.
Если операция чтения получения успешно считывает значение, записанное предыдущей операцией записи освобождения, то сама операция получения (по отношению к связанной с ней логике чтения) и все последующие операции в текущем потоке могут читать последнюю модификацию, внесенную в общую переменную потоком, владеющим операцией освобождения, до этого выпуска операция. Другими словами, все изменения, внесенные потоком, владеющим операцией освобождения, до операции освобождения, детерминированно видны всем операциям чтения в текущем потоке, которые происходят после этой операции получения.
Подводя итог, я попытался объяснить различное поведение порядка памяти C++, используя концепцию «видимости», как я ее понимаю. Исходя из этого, мои вопросы таковы:
Вопрос
Может ли мое понимание «видимости» правильно объяснить поведение порядка памяти C++ в большинстве сценариев? Если мое понимание неверно или ошибочно, не могли бы вы дать точное объяснение на уровне языка C++ (а не сосредотачиваться на низкоуровневых реализациях)?
(Дополнительное примечание: в местном техническом сообществе моего региона участники всегда склонны объяснять порядок памяти C++ с помощью системных принципов низкого уровня, таких как переупорядочение инструкций компилятора, переупорядочение инструкций ЦП и непоследовательное кэширование ЦП. Однако для меня эти низкоуровневые системы похожи на «черный ящик» — существуют многочисленные и сложные основные причины, которые могут привести к необычному поведению порядка памяти. Если преувеличивать, я мог бы даже случайно выдвинуть необоснованное утверждение вроде «это потому, что мой компьютер использует квантовый процессор, и нам нужно наблюдать квантовые биты, чтобы определить значение переменной». Короче говоря, я считаю, что объяснение порядка памяти C++ с помощью принципов ниже уровня языка C++ является одновременно односторонним и подвержено недоразумениям и ошибкам.)
Я пытался понять поведение различных порядков памяти, используя только одну концепцию [b]видимость[/b].
[list] [*][code]Visibility[/code]: (Ниже приводится мое понимание видимости, в котором основное внимание уделяется основной концепции «быть видимым».) [list] [code]Being visible[/code]: После того, как поток выполняет операцию записи в общую переменную между потоками, результат модификации, вызванный этой операцией записи, может быть успешно прочитан последующей операцией чтения другого потока. [*]Примечание: Антоним «видимый» еще не видимый, а не невидимый.
[code]Not yet visible[/code] означает, что модификация операции записи потока в общей переменной между потоками на данный момент не была прочитана операцией чтения другого потока (и может быть прочитана впоследствии). [/list]
[*][code]memory_order_relaxed[/code]: Этот порядок памяти гарантирует только то, что операции над соответствующей атомарной переменной являются атомарными (без промежуточных состояний). Однако для других потоков результат модификации этой атомарной операции временно находится в состоянии «пока не виден», и дополнительных ограничений, позволяющих избежать такой временной задержки, не существует.
[*][code]memory_order_release[/code]: Этот порядок памяти будет «упаковывать» результаты модификации всех операций записи, которые происходят до этой операции освобождения в текущем потоке (например, операции присваивания любых других неатомарных переменных или операции Memory_order_relaxed других атомарных переменных и т. д.). Когда другой поток успешно считывает значение, записанное этой операцией освобождения, посредством соответствующей операции получения, результаты модификации этих предыдущих операций записи могут быть детерминированно видимы для этого потока.
[*][code]memory_order_acquire[/code]: Этот порядок памяти гарантирует, что все операции чтения, происходящие после этой операции получения в текущем потоке, могут считывать допустимое состояние, полученное при выполнении операции получения. Если операция чтения получения успешно считывает значение, записанное предыдущей операцией записи освобождения, то сама операция получения (по отношению к связанной с ней логике чтения) и все последующие операции в текущем потоке могут читать последнюю модификацию, внесенную в общую переменную потоком, владеющим операцией освобождения, до этого выпуска операция. Другими словами, все изменения, внесенные потоком, владеющим операцией освобождения, до операции освобождения, детерминированно видны всем операциям чтения в текущем потоке, которые происходят после этой операции получения.
[/list]
Подводя итог, я попытался объяснить различное поведение порядка памяти C++, используя концепцию «видимости», как я ее понимаю. Исходя из этого, мои вопросы таковы: Вопрос Может ли мое понимание «видимости» правильно объяснить поведение порядка памяти C++ в большинстве сценариев? Если мое понимание неверно или ошибочно, не могли бы вы дать точное объяснение [b]на уровне языка C++ (а не сосредотачиваться на низкоуровневых реализациях)[/b]? (Дополнительное примечание: в местном техническом сообществе моего региона участники всегда склонны объяснять порядок памяти C++ с помощью системных принципов низкого уровня, таких как переупорядочение инструкций компилятора, переупорядочение инструкций ЦП и непоследовательное кэширование ЦП. Однако для меня эти низкоуровневые системы похожи на «черный ящик» — существуют многочисленные и сложные основные причины, которые могут привести к необычному поведению порядка памяти. Если преувеличивать, я мог бы даже случайно выдвинуть необоснованное утверждение вроде «это потому, что мой компьютер использует квантовый процессор, и нам нужно наблюдать квантовые биты, чтобы определить значение переменной». Короче говоря, я считаю, что объяснение порядка памяти C++ с помощью принципов ниже уровня языка C++ является одновременно односторонним и подвержено недоразумениям и ошибкам.)