#c
#c
Вопрос:
В книге «Параллелизм C в действии» есть пример:
класс background_task { общедоступный: оператор void() () const { do_something(); do_something_else(); } }; background_task f; std::thread my_thread(f);
Далее следует текст: «В этом случае предоставленный объект функции копируется в хранилище, принадлежащее вновь созданному потоку выполнения, и вызывается оттуда. Поэтому важно, чтобы поведение копии было эквивалентно оригиналу, иначе результат может оказаться не таким, как ожидалось.»
Не мог бы кто-нибудь, пожалуйста, объяснить мне более подробно, что означают эти два предложения? Как насчет других вызываемых типов, которые могут быть предоставлены конструктору объекта потока, они не скопированы? Как мне убедиться, что «копия ведет себя эквивалентно оригиналу» или почему она не будет вести себя эквивалентно? Спасибо!
Ответ №1:
Инструкция сравнивает данный пример с приведенным непосредственно перед этим случаем, когда обычная функция void do_some_work();
передается в качестве аргумента в std::thread
.
std::thread my_thread(do_some_work);
Объект функции background_task f
должен быть копируемым. Это невозможно, если class background_task
состоит из чего-то, что делает его недоступным для копирования. Например, если
background_task
имеет std::mutex
, он не будет копируемым, потому что std::mutex
не может быть скопирован или перемещен. Смотрите демонстрацию.
Во-вторых, даже если background_task
можно скопировать, следует убедиться, что конструктор копирования создает точную копию оригинала. Примером того, где этого не происходит, является хорошо известный случай, когда класс имеет необработанные указатели, а конструктор копирования не выполняет глубокое копирование.
Вызываемый объект void do_some_work();
также копируется в поток подобно объекту функции, но не сталкивается с проблемами, упомянутыми выше.
Ответ №2:
Здесь особо нечего читать.
Вызываемый объект, каким бы он ни был, должен быть скопирован в поток, иначе его вызов не будет потокобезопасным.
И если вызываемый объект относится к типу, который имеет, скажем так, «неожиданную» семантику копирования (подумайте, действительно странно написанный конструктор копирования), то это просто плохие новости для всех, кто пытается использовать ваш код.
Вот и все!