энергозависимый как механизм синхронизации - PullRequest
5 голосов
/ 10 мая 2011

Допустим, у меня есть класс Foo, и у него есть статическая переменная-член с именем Count (тип - целое число).Эта переменная использовалась в многопоточном приложении, и я использовал механизм синхронизации блокировки перед выполнением любых операций чтения / записи в эту переменную.Когда я читаю эту статью Volatile , у меня складывается впечатление, что я могу удалить все эти блокировки вокруг этой переменной и просто использовать ключевое слово volatile при объявлении этой переменной.Это должно заботиться обо всем, что связано с синхронизацией.Это правильно?Каковы плюсы и минусы этого подхода?

Ответы [ 3 ]

8 голосов
/ 10 мая 2011

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

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

Каковы плюсы и минусы этого подхода?

Плюсы в том, что он может составлять несколько наносекундбыстрее, чтобы избежать блокировки.Минусы: если вы неправильно запрограммируете низкий уровень блокировки, то ваша программа выглядит так, как будто она работает нормально, а затем имеет причудливые режимы сбоев, которые невозможно отладить или воспроизвести.

Вы должны использовать только низкий уровеньРешение с блокировкой, когда ваш анализ производительности позволил вам сделать вывод, что решение с низким уровнем блокировки - это only способ достижения цели производительности, которую ваши клиенты требуют от вас.И вы должны использовать решение с низким уровнем блокировки только тогда, когда у вас есть тщательное и deep понимание каждой оптимизации, которую каждый возможный процессор, на котором когда-либо будет работать ваша программа, может выполнять с низким уровнем блокировкикод.Вам нужно будет глубоко понять модель памяти, которую вам гарантирует CLR, что гарантирует оборудование и каковы все различия.

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

4 голосов
/ 10 мая 2011

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

Например, если вы пишете это:

Count = Count + 1;

Помните, что приращение требует трех операций: чтение, приращение, запись.В нескольких потоках может возникнуть проблема.Представьте, что начальное значение Count равно нулю.

  • Поток 1 читает Count (значение 0)
  • Поток 2 читает Count (значение 0)
  • Поток1 увеличивает свое значение (1)
  • поток 1 записывает счет (значение 1)
  • поток 2 увеличивает свое значение (1)
  • поток 2 записывает счет (значение 1)

Конечное значение Count равно 1, когда оно должно быть 2.

Вы хотите взглянуть на класс Interlocked .В частности, Interlocked.Increment и Interlocked.CompareExchange.

1 голос
/ 10 мая 2011

Ключевое слово volatile полностью отличается от lock.lock подразумевает, что существует несколько операторов, которые должны выполняться как единая единица работы с согласованным состоянием, например, если вы хотите убедиться, что никакие другие потоки не могут добавлять или удалять элементы из коллекции, пока вы обращаетесь кконкретный предмет из коллекции или подсчет предметов в коллекции.Ключевое слово volatile влияет на поведение компилятора при попытке оптимизировать ваш код, когда он генерирует машинные инструкции из вашего исходного кода.Возможно, что компилятор может переупорядочить операторы в определенном блоке кода таким образом, чтобы это не повлияло на этот блок кода, но это переупорядочение может быть недопустимым, если значение вашей переменной можно изменить из другого потока.Использование volatile говорит компилятору не учитывать такие оптимизации и всегда читать значение вашей переменной из памяти, а не из кэшированного регистра.

Джон Скит обсуждает это более подробно в своей статье Volatility, Атомарность и блокировка .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...