Безопасность потоков с памятью, выделенной кучей

Я читал это: http://en.wikipedia.org/wiki/Thread_safety

Является ли следующая функция безопасной для потоков?

void foo(int y){
    int * x = new int[50];
    /*...do some stuff with the allocated memory...*/
    delete [] x;
}

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

Изменить: Ах. Похоже, я неправильно понял эту часть статьи:

Подпрограмма является реентерабельной и, следовательно, потокобезопасной, если

  • единственными переменными, которые он использует, являются из стека

(я понял, что

Подпрограмма является реентерабельной и, следовательно, потокобезопасной, если и только если

  • единственными переменными, которые он использует, являются из стека

что в соответствии с приведенными ниже ответами не так)

Ответ 1

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

Хотя память находится в куче, указатель на нее находится в стеке. Только ваш поток имеет указатель на эту память, и поэтому нет риска одновременной модификации - ни один другой поток не знает, где память должна его модифицировать.

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

Ответ 2

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

new и delete обычно реализуются поточно файловым способом (не уверен, что стандарт гарантирует это), поэтому ваш код, вероятно, будет в порядке.

Плюс обычные рекомендации по использованию std::vector вместо того, чтобы вручную выделять массив, но я предполагаю, что вы только предоставили это в качестве примера:)

Ответ 3

new и delete могут быть или не быть потокобезопасными. Они, вероятно, есть, но это зависит от реализации. Видеть: С++ новая безопасность потока оператора в Linux и gcc 4

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