2009-04-13 2 views
6

я делаю следующее рассуждение, пожалуйста, скажите мне, что это неправильно (или вправо) о нем:Есть встроенные функции в C/C++, чтобы сделать их потокобезопасными?

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

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

Thanks

+0

Локальные переменные функции всегда дублируются для каждого экземпляра выполняемой функции. –

+2

Не так, если переменная объявлена ​​статической. Статические переменные сохраняют значения между вызовами функций и не дублируются. – sharptooth

+1

Хорошо, понял. Локальные переменные помещаются в стек, верно? – alvatar

ответ

25

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

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

+2

Встроенная декларация может быть подсказкой, однако __forceinline принудительно в MSVC;) – RandomNickName42

28

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

2

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

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

6

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

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

1

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

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() не поточно, потому что нет никакого кода предотвращения любого другого потока от выполнения кода. Выполнение функции inline не мешает doTheThing() быть вызванным несколькими потоками одновременно. Чтобы обеспечить безопасный поток doTheThing(), вам необходимо убедиться, что он не вызывается параллельно или какие-либо общие (нелокальные) данные, к которым вы обращаетесь, защищены.

+0

Я не сказал, что это была небезопасная тема; Я сказал, что это не потоковая безопасность. Это не расщепление волос. Понимание различий между потокобезопасными, небезопасными и небезопасными - это разница между людьми, которые сталкиваются с многопоточным процессом и людьми, которые этого не делают. –

+0

Если вы не знаете реализацию getTheAnswers(), вы не можете сказать, что это поточно-безопасный. Подпись, вызванная вызовом (вектор * getTheAnswers;), конечно, не предполагает, что это так. –

+0

ОК, то это что-то подсказывает вам - что он выделяет вектор и возвращает его. Это может быть или не быть правдой. Но даже если это так, как это сделать? Копирует ли он элементы из какого-либо глобального вектора? Доступ к глобальному вектору стал безопасным для потоков? Дело в том, что вы не знаете. –

2

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

+0

не полезный ответ. – alvatar

+1

Почему? Единственный способ программирования потоковой безопасности - узнать о безопасности потоков. И из того, что я вижу, мой ответ по-прежнему остается единственным, который предоставляет вам ссылку на некоторые чтения, чтобы получить более глубокое понимание этого вопроса. – lothar

+0

Да, вы правы, что вы даете мне ссылку. Но для статьи в википедии о потокобезопасности мне не нужно спрашивать в SO. Кроме того, я прошу причины. Во всяком случае, я удалил свой downvote. – alvatar

2

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

0

Совсем нет.

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

Таким образом, даже если компилятор выполнил то, что вы предложили (что не должно, как говорили другие), все равно не сделает его потокобезопасным.

-2

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

3

Встраивание и безопасность резьбы являются ортогональными, то есть несвязанными понятиями.

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

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

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

+0

спасибо за этот поздний ответ :). У меня теперь есть четкие концепции, но ваш код очень показателен. Благодаря! – alvatar

+0

Было приятно :) – Tobias

3

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

Смежные вопросы