考虑以下代码(摘自 Simple-Web-Server,但不需要了解该库即可回答这个问题):
HttpServer server;
thread server_thread;
server.config.port = 8080;
server.default_resource["GET"] = [](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
string content = "Hello world!"
*response << "HTTP/1.1 200 OK\r\nContent-Length: " << content.size() << "\r\n\r\n" << content;
};
server_thread = thread([&server]() {
server.start();
});
HttpServer::default_resource
是一个std::unordered_map,据我所知,它不是线程安全的。 port
是一个无符号短整型。
假设我对C++内存屏障的理解是正确的,那么在新线程中看到的server
可能不处于有效状态,因为主线程可能还没有将port
和default_resource
的更改写入到其他线程可以访问的内存中。因此,server.start()
可能无法正常工作。
要修复这个问题,我需要通过添加atomic_thread_fence
来更改代码:
HttpServer server;
thread server_thread;
server.config.port = 8080;
server.default_resource["GET"] = [](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
string content = "Hello world!"
*response << "HTTP/1.1 200 OK\r\nContent-Length: " << content.size() << "\r\n\r\n" << content;
};
atomic_thread_fence(memory_order_release);
server_thread = thread([&server]() {
atomic_thread_fence(memory_order_acquire);
server.start();
});
我的理解正确吗?这两个 atomic_thread_fence
都是必须的吗?
std::thread::thread()
之前,由于服务器已经被初始化,所以不需要使用线程屏障。 - Thomas Russell