Создать объект в потоке A, использовать в потоке B. Требуется Mutex?

Я читал разные вещи при многопоточности, С++, правильной синхронизации и блокировках, чтобы предотвратить условия гонки. Однако мне не ответил один вопрос: Требуется ли mutex, если я создаю объект в потоке A, но использую его исключительно в потоке B после?

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

Самый простой пример для визуализации того, что я имею в виду

struct Object {
    void do_stuff();
};

Object o;
std::thread worker_thread([&o](){
    while (alive)
        o.do_stuff();
}).join();
// `o` is never used outside worker_thread

Я был бы рад, если бы вы могли также порекомендовать мне статьи/книги, где я могу больше читать эту тему и/или правильные ключевые слова для поиска этих сценариев.

Ответы

Ответ 1

Это нормально, вам не нужен mutex.

Создание потока задает барьер памяти, поэтому безопасно получить доступ к o через ссылку, переданную в worker_thread.

§ 30.3.2.2-6 - [thread.thread.constr]

Завершение вызова конструктора синхронизируется с началом вызова копии f.

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

Соединение нити также устанавливает барьер, поэтому после присоединения worker_thread вы можете снова получить доступ к o в своем основном потоке.

§ 30.3.2.5-4 - [thread.thread.destr]

Пополнение потока, представленное *, синхронизируется с (1.10) соответствующим успешным соединением join().

Для дальнейшего чтения:

  • Энтони Уильямс написал хорошую книгу о параллельном программировании (С++ concurrency в действии)
  • Книга Bjarne Stroustrup (язык программирования С++, 4-е издание) имеет две прекрасные главы по параллельному программированию.
  • Jeff Preshing имеет хороший блог о многих из этих тем; проверить preshing.com