Кешируются ли объекты синхронизации? - PullRequest
0 голосов
/ 07 июля 2011

Я новичок в многопоточном мире и начал в него входить. Я нашел поток требует синхронизации. Летучие больше не надежная вещь. Я хотел бы знать, кешируется ли объект синхронизации компилятором или на каком-либо этапе?

Используемая платформа / языки: c ++, win32, Windows

В c ++ ключевое слово volatile используется для объектов, которые не могут быть кэшированы ЦП. Но сегодняшние компиляторы не строго следуют этому. Есть ли другой способ сделать объекты синхронизации не кэшируемыми (или другие оптимизации не применяются к этим объектам).

tl; dr: Кешируются ли объекты синхронизации? Если да, как вы можете сделать его не кэшируемым?

Ответы [ 3 ]

1 голос
/ 07 июля 2011

Я не уверен, что следую вашему вопросу: кеш компилятора почти не связан с многопоточностью. Единственное, что может сделать кеш компилятора, это увеличить скорость компиляции за счет кэширования предыдущих компиляций.

Объекты синхронизации можно «кэшировать», поскольку они являются любыми произвольными объектами, которые вы решили использовать для синхронизации, но это мало влияет на параллелизм. Единственная вещь, о которой вам нужно заботиться при синхронизации, это то, что когда у вас несколько потоков, конкурирующих за ресурс, все они должны синхронизироваться на одном и том же объекте, чтобы получить доступ для чтения / записи к ресурсу.

Я собираюсь сделать дикое предположение, основанное на вашем упоминании volatile, и предположить, что вы обеспокоены тем, что объект синхронизации может кэшироваться в локальном кэше потока, а изменения объекта синхронизации из одного потока могут не выполняться. виден другой ветке. Это, однако, ошибочная идея:

  1. Когда вы вызываете lock () или synchronize () (в зависимости от языка), все, что вам нужно, это заботиться о том, чтобы блокировка выполнялась для одного и того же объекта независимо от внутреннего состояния объекта.
  2. Как только вы получили блокировку объекта, любой ресурс, который вы изменяете в этой области блокировки, будет изменен только одним потоком.
  3. Как правило, вы должны использовать объект синхронизации, который не изменится (в идеале только для чтения, const или final), и мы говорим здесь только о ссылке, а не о содержании самого объекта. Вот пример:

    object sync = new object (); строка что-то = "привет":

    void ModifySomething () { sync = new object (); // <- ВЫ НЕ ДОЛЖНЫ ДЕЛАТЬ ЭТОГО !! Блокировка (синхронизация) { что-то = GenerateRandomString (); <br> } }

Теперь обратите внимание, что каждый раз, когда поток вызывает ModifySomething, объект синхронизации будет заменен новым объектом, и потоки никогда не будут синхронизироваться на одном и том же объекте, поэтому могут быть одновременные записи в something.

0 голосов
/ 07 июля 2011

Объекты синхронизации обязательно управляются ОС, которая также управляет потоками и кэшем.Поэтому ответственность за работу с кешами лежит на ОС.Если он каким-то образом знает, что объект синхронизации используется только на одном процессоре (например, потому что он не выделил второй процессор для вашего процесса), ОС вполне может решить сохранить объект синхронизации в кеше первого процессора.Если его необходимо разделить между процессорами, это тоже произойдет.

Одним из практических последствий является то, что вы всегда будете инициализировать объекты синхронизации.В C ++ это естественно (об этом заботится конструктор), но в других языках вы должны делать это явно.ОС должна отслеживать объекты синхронизации.

0 голосов
/ 07 июля 2011

Вопрос не имеет особого смысла без указания среды выполнения.


В случае Java , скажем, объект синхронизации (объект, используемый для синхронизации) аналогичен любому другому объекту. объект является целью синхронизации, поэтому volatile (который применяется к переменным-членам) необходим только в том случае, если переменная , содержащая объект синхронизации , может измениться. Я бы избегал разработки программы, которая нуждается в таких конструкциях.

Помните (опять же, в Java), это оценка выражения - обычно это переменный доступ - который приводит к использованию объекта синхронизации. Эта оценка ничем не отличается от любой другой в этом аспекте.

В конце концов, однако, он просто использует инструменты синхронизации определенной среды выполнения / среды таким образом, чтобы они были четко определены и хорошо себя вели.

Счастливого кодирования.


Java, например, гарантирует, что synchronized(x) { foo }, где x является конкретным объектом, создаст взаимоисключающую критическую область, в которой выполняется foo. Для этого он должен выполнить внутреннюю работу, чтобы гарантировать, что данные бухгалтерского учета корректно сбрасываются на все процессоры / кэши. Тем не менее, эти детали, как правило, выходят за рамки времени выполнения с точки зрения использования конструкции синхронизации.

...