Правда что в C# все записи volatile? Вне зависимости помечана переменная как volatile или нет.здесь
However, in C# all writes are volatile (unlike say in Java), regardless of whether you write to a volatile or a non-volatile field. So, the above situation actually never happens in C#.
Здравствуйте, Ellin, Вы писали:
E>Правда что в C# все записи volatile? Вне зависимости помечана переменная как volatile или нет.здесь
E>
E>However, in C# all writes are volatile (unlike say in Java), regardless of whether you write to a volatile or a non-volatile field. So, the above situation actually never happens in C#.
Однако тут MS говорит: "Also, the variable is declared to be volatile to ensure that assignment to the instance variable completes before the instance variable can be accessed."
P_A>Однако тут MS говорит: "Also, the variable is declared to be volatile to ensure that assignment to the instance variable completes before the instance variable can be accessed."
Здравствуйте, Ellin, Вы писали:
E>Правда что в C# все записи volatile?
Читаем источник:
The mainstream x86 and x64 processors implement a strong memory model where memory access is effectively volatile. So, a volatile field forces the compiler to avoid some high-level optimizations like hoisting a read out of a loop, but otherwise results in the same assembly code as a non-volatile read.
с оговоркой про чтение:
The x86/x64 instruction set actually does contains three fence instructions: LFENCE, SFENCE, and MFENCE. .. MFENCE is useful to go around one particular issue: if a core reads a memory location it previously wrote, the read may be served from the store buffer, even though the write has not yet been written to memory. I don’t actually know whether the CLR JIT ever inserts MFENCE instructions.
С итаниумами разруливается (в теории) JITом.
В общем помечайте переменные, к которым вы явно или неявно обращаетесь из нескольких потоков без lock { } и будет вам щастье.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Ellin, Вы писали:
E>>Правда что в C# все записи volatile? S>Читаем источник:
S>
S>The mainstream x86 and x64 processors implement a strong memory model where memory access is effectively volatile. So, a volatile field forces the compiler to avoid some high-level optimizations like hoisting a read out of a loop, but otherwise results in the same assembly code as a non-volatile read.
S>с оговоркой про чтение: S>
S>The x86/x64 instruction set actually does contains three fence instructions: LFENCE, SFENCE, and MFENCE. .. MFENCE is useful to go around one particular issue: if a core reads a memory location it previously wrote, the read may be served from the store buffer, even though the write has not yet been written to memory. I don’t actually know whether the CLR JIT ever inserts MFENCE instructions.
S>С итаниумами разруливается (в теории) JITом.
S>В общем помечайте переменные, к которым вы явно или неявно обращаетесь из нескольких потоков без lock { } и будет вам щастье.
При volatile записи кеш процессора сбрасывается (анулируется). Если каждая запись volatile, то кеш практически вообще не используется. В чем тогда смысл lowlock?
Здравствуйте, Ellin, Вы писали:
E>При volatile записи кеш процессора сбрасывается (анулируется). Если каждая запись volatile, то кеш практически вообще не используется. В чем тогда смысл lowlock?
Ну что Вы, volatile к кэшу не имеет никакого отношения. Оно запрещает перемещать инструкции, обращающиеся к данной переменной, относительно остальных. Кроме того, оно запрещает компилятору кэшировать значения таких переменных, например в регистрах процессора, и каждое такое обращение будет обращением к ячейке памяти. А вот будет-ли при этом сброшен кэш (точнее, конкретная линейка кэша), зависит вовсе не от volatile, а от состояния этой самой линейки.
Это, кстати, несколько раз за последнее время сдесь обсуждалось
Здравствуйте, Ellin, Вы писали:
E>При volatile записи кеш процессора сбрасывается (анулируется). Если каждая запись volatile, то кеш практически вообще не используется.
И снова читаем источник, практически те же два абзаца:
The processors may not bother to keep those caches coherent by default, and special instructions may be needed to flush and refresh the caches.
The mainstream x86 and x64 processors implement a strong memory model where memory access is effectively volatile.
Как оно на самом деле — к вендорам.
Даже для итаниумов речь о "сбрось кэш" (точнее, о рефреше) идёт только для volatile read:
Instruction LD.ACQ effectively says, “refresh my cache and then read a value” and ST.REL says, “write a value to my cache and then flush the cache to main memory”
Здравствуйте, Sinix, Вы писали:
S>Даже для итаниумов речь о "сбрось кэш" (точнее, о рефреше) идёт только для volatile read: S>[q] S>Instruction LD.ACQ effectively says, “refresh my cache and then read a value” and ST.REL says, “write a value to my cache and then flush the cache to main memory”
Это довольно вольная интерпретация документации автором блога Вот здесь более строго изложено.
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, Ellin, Вы писали:
JR>Боюсь, несколько вольное использование автором блога терминологии, без уточнения используемых терминов, запутывает ситуацию.
JR>Что он подразумевает под кэшем, когда пишет
JR>
JR>you can imagine each thread as having its own cache
JR>не очень понятно. Можно понять как некоторое локальное хранилище, связанное с конкретным потоком, но речь явно идёт не о кэше процессора.
Тогда у меня возникает вопрос. Допустим есть ПК с двумя процессорами. Может ли один поток выполняться на одно процессоре а чере секунду возобнавить свое выполнение на другом процессоре. Соответсвенно кеш процессора на одном процессоре один, а через секунду это уже кеш второго процессора, где совсем другие значения.
Там есть таблица в разделе "Memory model and .NET operations"
Volatile write / Flushes thread cache after?/ Yes.
Вот я и подумал что скидывает кеш. Но это оказывается некий кеш потока...
E>Допустим есть ПК с двумя процессорами. Может ли один поток выполняться на одно процессоре а чере секунду возобнавить свое выполнение на другом процессоре. Соответсвенно кеш процессора на одном процессоре один, а через секунду это уже кеш второго процессора, где совсем другие значения.
Да, это вполне реальная ситуация, и для её разруливания существует специальный механизм — cache coherency.
Я-бы, пожалуй, поостерёгся называть себя знатоком деталей , но в общем виде это выглядит так.
Когда процессор(1) изменяет данные в одной из линеек кэша, то извещения об этом рассылается остальным процессорам. Если у другого процессора(2) есть линейка с данными, загруженными из того-же адреса, то эта линейка помечается как недействительная. Если теперь этот процессор(2) попытается прочитать данные из этой линейки, то процессор(1) получит требование "сбросить" данную линейку в ОЗУ, а процессор(2) произведёт обновление своей линейки из ОЗУ, и только после этого произведёт операцию чтения из кэша.
Таким образом, как только поток, переключившийся на другой процессор, попытается прочитать какие-то данные, эти данные будут загружены в кэш этого процессора.