Сколько стоит ключевое слово volatile в многопроцессорной системе? - PullRequest
11 голосов
/ 16 июня 2009

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

class foo {
  static volatile instance;
  static object l = new object();

  public static foo Instance {
    if (instance == null)
      lock(l) {
        if (instance == null)
          instance = new foo();
      }

    return foo();
  }
}

это работает на 8-канальной машине, и мы наблюдаем переключение контекста на частоту 500 000 в секунду. типичные системные ресурсы хороши - загрузка процессора 25%, загрузка памяти 25%, низкий ввод-вывод, отсутствие подкачки и т. д.

вызывает ли использование изменчивого поля барьер памяти или какую-либо перезагрузку кеша процессора? или он просто идет за основной памятью каждый раз, только для этого поля?

Ответы [ 6 ]

4 голосов
/ 16 июня 2009

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

По данным этого сайта :

В ключевом слове volatile C # реализована семантика получения и выпуска, которая подразумевает барьер чтения памяти при чтении и барьер памяти записи при записи.

3 голосов
/ 19 июня 2009

Одна из вещей, которую volatile не сделает, - это переключение контекста. Если вы видите 500 000 переключений контекста в секунду, это означает, что ваши потоки что-то блокируют, а volatile является , а не виновником.

1 голос
/ 16 июня 2009

К сожалению, синглтон терпит неудачу практически за все :)

Это не моя область знаний, но, насколько я знаю, в volatile нет ничего особенного, кроме того, что компилятор / среда выполнения НЕ переупорядочивает чтение / запись (в переменную) для целей оптимизации.

Редактировать: Я исправлен. Изменчивость не только создает барьеры памяти, но и то, что происходит (и, между прочим, производительность), во многом зависит от конкретного процессора. Смотри http://dotnetframeworkplanet.blogspot.com/2008/11/volatile-field-and-memory-barrier-look.html

Вот почему вам все еще нужен замок.

Вопросы, на которые, возможно, не ответили уже:

  1. Что на самом деле делает ваш экземпляр-синглтон? Может быть, код экземпляра нуждается в рефакторинге ...
  2. Каков счет потока запущенного процесса? Коробка с 8 путями не поможет вам, если у вас ненормально большое количество потоков.
  3. Если это выше, чем ожидалось, почему?
  4. Что еще работает в системе?
  5. Устранена ли проблема с производительностью?
0 голосов
/ 29 мая 2015

Краткий ответ: да, он создает барьер памяти (сбрасывает все и уходит в основную память, а не только в эту переменную), но нет, это не будет причиной переключения контекста.

Кроме того, как уже упоминали другие, я не считаю, что здесь необходима изменчивость.

0 голосов
/ 16 июня 2009

Нет необходимости использовать volatile для синглтона, поскольку вы устанавливаете его ровно один раз - и блокируете код, который его устанавливает. См. статью Джона Скита о синглетонах для получения дополнительной информации.

0 голосов
/ 16 июня 2009

В вашем примере, volatile не должно быть предметом какого-либо "замедления". Однако блокировка () может включать в себя огромные обходы ядра, особенно если за блокировку много споров.

В этом случае нет необходимости блокировать ваш синглтон, вы можете просто делать

class Foo {
  static Foo instance = new Foo();
  public static Foo FooInstance() {
    return instance ;
  }
}

Конечно, если 'instance' используется во многих различных потоках, вам все равно придется блокировать () все, что изменяет этот Foo, если все методы / свойства Foo не доступны только для чтения. например,

 class Foo {
      static Foo instance = new Foo();
      object l = new object();
      int doesntChange = 42;
      int canChange = 123;
      public static Foo FooInstance() {
        return instance ;
      }
      public void Update(int newVal) {
         lock(l) { // you'll get a lot of trouble without this lock if several threads accesses the same FOO. Atleast if they later on read that variable 
            canChange = newVal;
         }

      public int GetFixedVal() {
         return doesntChange; //no need for a lock. the doesntChange is effectivly read only
      }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...