Сколько стоит ключевое слово volatile в многопроцессорной системе?

StackOverflow https://stackoverflow.com/questions/1002739

  •  05-07-2019
  •  | 
  •  

Вопрос

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

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%, низкий уровень ввода-вывода, отсутствие подкачки и т. д.

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

Это было полезно?

Решение

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

Согласно этому сайт :

  

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

Другие советы

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

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

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

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

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

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

<Ол>
  • Что на самом деле делает твой экземпляр-синглтон? Возможно, код экземпляра нуждается в рефакторинге ...
  • Каков счет потока запущенного процесса? Коробка с 8 путями не поможет вам, если у вас ненормально большое количество потоков.
  • Если оно выше ожидаемого, почему?
  • Что еще работает в системе?
  • Устранена ли проблема с производительностью?
  • В нашем примере volatile не должно быть предметом какого-либо "замедления". Однако lock () может включать в себя огромные обходы ядра, особенно если за блокировку много споров.

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

    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
          }
        }
    

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

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

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top