【发布时间】:2014-06-10 18:38:33
【问题描述】:
我想在构造函数中初始化一个字段,之后再也不更改它。我希望保证在构造函数完成后,每次读取该字段都会读取初始化值,无论读取发生在哪个线程中。
基本上,我想要的保证与 Java 中的 final 字段相同。
这是我尝试过的:
#include <atomic>
#include <iostream>
#include <thread>
struct Foo
{
Foo(int x) : x(x)
{
// ensure all writes are visible to other threads
std::atomic_thread_fence(std::memory_order_release);
}
int x;
};
void print_x(Foo const& foo)
{
// I don't think I need an aquire fence here, because the object is
// newly constructed, so there cannot be any stale reads.
std::cout << foo.x << std::endl;
}
int main()
{
Foo foo(1);
std::thread t(print_x, foo);
t.join();
}
- 这是否保证始终打印
1或线程t观察foo.x处于未初始化状态? - 如果不使用成员初始化器
x(x)而是使用显式赋值this->x = x;会怎样? - 如果
x不是int而是某个类类型怎么办? - 将
x设为const int是否会改变线程安全方面的任何内容?
【问题讨论】:
-
巧合的是,您正在将
foo的副本传递给新生成的线程。如果您确实打算传递对foo的引用,则需要将其传递到引用包装器中,例如std::thread t(print_x, std::cref(foo));或 - 对于非常量引用 -std::thread t(print_x, std::ref(foo));。
标签: c++ multithreading