Безопасность потоков с памятью, выделенной кучей
Я читал это: 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
Чтобы быть потокобезопасным, функция должна либо использовать переменные стека, либо синхронизировать свой доступ к другим ресурсам с другими потоками. До тех пор, пока отдельные вызовы нового выделяют различное пространство в куче при вызове из разных потоков, вы должны быть в порядке.