Являются ли встроенные функции в C / C ++ способом сделать их поточно-ориентированными? - PullRequest
6 голосов
/ 13 апреля 2009

Я делаю следующие рассуждения, пожалуйста, скажите мне, что не так (или правильно) в этом:

"Если встраивание функции дублирует код в месте вызова функции, то статические и локальные переменные дублируются для каждой вызывающей ее функции, и если существует только один поток, выполняющий функцию, которая вызывает встроенный одновременно время, то код является потокобезопасным ".

"А если это не помогает со статическими и глобальными переменными, то с кодом, создающим временные переменные?"

Спасибо

Ответы [ 11 ]

28 голосов
/ 13 апреля 2009

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

25 голосов
/ 13 апреля 2009

Когда вы объявляете функцию как встроенную, это просто подсказка компилятору. Статические переменные имеют четкое определение в языке. Если компилятор действительно встроил функцию, он по-прежнему обязан сохранять статические переменные общими для всех экземпляров функции. Следовательно, они останутся глобальными и должны быть защищены в среде MT.

Что касается локальных переменных, если они не используются вне функции, они являются потокобезопасными независимо от того, включена функция или нет.

6 голосов
/ 13 апреля 2009

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

Но если вы обращаетесь к статической переменной или переменной-члену класса, все проблемы, связанные с многопоточностью (повреждение переменной, потерянное обновление ...), по-прежнему будут существовать независимо от того, встроен он или нет. 1003 *

3 голосов
/ 12 июля 2012

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

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

Накладные и резьбовые соединения ортогональны, т. Е. Несвязанные понятия.

Рассмотрим эти функции:

int factorial(const int n)
{
  if (n <= 1)
  {
    return 1;
  }

  return factorial(n - 1);
}

Эта функция не может быть встроенной, так как она рекурсивная, но в то же время совершенно поточно-ориентированная.

int factorial_2(int n)
{
  int Result = 1;

  while (n > 1)
  {
    Result *= n--;
  }

  return Result;
}

Эта функция может быть встроена компилятором и по-прежнему идеально ориентирована на многопотоковое исполнение.

int RefCount;

void DecRef()
{
  --RefCount;
}

Эта функция не является поточно-ориентированной независимо от того, встроен ли компилятор в нее или нет.

2 голосов
/ 13 апреля 2009

На вашем месте я бы не использовал статические переменные внутри встроенных функций. Более старые версии стандарта C ++ требовали иного значения, нежели текущее.

2 голосов
/ 13 апреля 2009

Безопасность потока не имеет никакого отношения к встраиванию. Тот факт, что каждый поток выполняет копию одного и того же кода, не делает его безопасным для доступа к общим данным. Обязательно прочтите Thread thread перед началом многопоточного программирования.

2 голосов
/ 13 апреля 2009

Существуют (или, возможно, были ) глючные компиляторы, которые дублируют статические переменные для каждой вставки вмещающей функции. Это не намеренное поведение.

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

1 голос
/ 13 апреля 2009
Встраивание

не влияет на то, является ли функция поточно-ориентированной. Например:

inline void doTheThing()
{
   int a = 42; // this is thread safe, but it would be anyway
   vector<int> * answers = getTheAnswers(); // this is not thread safe
}

Доступ к вектору, на который указывает getTheAnswers (), не является потокобезопасным, поскольку нет кода, препятствующего выполнению кода любым другим потоком. Включение функции в линию не препятствует тому, чтобы doTheThing () вызывался несколькими потоками одновременно. Чтобы сделать поток doTheThing () потокобезопасным, вам нужно убедиться, что он не вызывается параллельно или все общие (нелокальные) данные, к которым вы обращаетесь, защищены.

0 голосов
/ 14 апреля 2009

Все статические переменные в (обычных и встроенных) функциях попадают в кучу. Куча НЕ БЕЗОПАСНАЯ НИТЯ .

...