Параллелизм и синхронизация
-
29-09-2019 - |
Вопрос
Представьте, что вы используете параллелизм в многоядерной системе.
Разве не возможно, что те же инструкции могут быть выполнены одновременно?
Возьмите следующий код:
int i = 0;
if( blockingCondition )
{
lock( objLock )
{
i++;
}
}
В моей голове кажется, что в системе с несколькими ядрами и параллелизмом вполне возможно, что в тот же момент можно проверить блокировку в тот же момент, что приводит к попытке блокировки, и так далее ... это истинный?
Если это так, как вы можете обеспечить синхронизацию в процессорах?
Кроме того, обрабатывает ли .NET TPL этот тип синхронизации? А как насчет других языков?
РЕДАКТИРОВАТЬОбратите внимание, что это нет о нитках, но задачах и параллельно-процессе.
Редактировать 2Хорошо, спасибо за информацию всех. Итак, правда ли, что ОС гарантирует, что запись в память сериализуется, обеспечивая многоядерную синхронизацию через WALTILE READS?
Решение
Замок, как вы описали здесь, это «Монитор«Стиль блокировки на OBJLOCK. Как вы уже отмечали, все возможное, в рамках многоядерной системы, для двух« заблокированных »вызовов начинать одновременно. Тем не менее, любая среда применения высокого уровня, которая использует мониторы, будет переведена на монитор в семафор Запросы (или, в зависимости от вашей ОС и языковых подробностей, запросов MUTEX) в скомпилированном байтовом коде.
Семафоры реализуются на операционной системе и / или уровнях оборудования, а языки более высокого уровня связывают с ними. На уровне ОС они «гарантированы», чтобы быть атомным. То есть любая программа, приобретая семафор, гарантированно будет единственным, что делает так в этот момент. Если две программы или два потока в рамках программы пытаются приобрести блокировку одновременно, один пойдет первым (и преуспеть), а другой пойдет второй (и сбой).
На этом этапе «как вы гарантируете синхронизацию», чтобы быть проблемой для программиста приложения, и начинает быть проблемой для дизайнера операционной системы и дизайнера аппаратного обеспечения.
В результате этого, как кодера приложения, вы можете с уверенностью предположить, что «Lock (objlock)» будет атомным вызовом, независимо от того, сколько процессоров вы подключаете к своей системе.
Другие советы
Чтобы понять, почему это работает, имейте в виду:
Блокировка блокировки (т.е. увеличение замка семафор на объекте) - это операция, которая блокирует, если объект уже заблокирован.
Два шага
lock
, а) проверка семафора блокировки бесплатна, б) и фактически запирает объект, выполняется'одновременно' - то есть они монолит или атомный Операция в отношении взаимосвязи между процессором и памятью.
Следовательно, вы можете увидеть это, если 2 потока введите свой if
-block, одна из двух потоков приобретет замок, а другая будет блокировать, пока первый не закончил if
.
Ваша забота именно поэтому нам нужен специальный механизм, как lock
и не может просто использовать логический флаг.
Решение вашей «одновременной» проблемы в алгоритме, который lock
(который звонит Monitor.Enter()
) использует. Он включает в себя барьеры памяти и знание очень низкоуровневой механики памяти, чтобы гарантировать, что нить № 2 может приобрести блокировку одновременно.
Примечание: я говорю о .NET только, а не Java.