【问题标题】:Guarantees when starting a Boost thread启动 Boost 线程时的保证
【发布时间】:2016-01-26 12:34:10
【问题描述】:

我正在使用 don't supports the C++ 11 memory model 的 Boost 和 Visual Studio 2013。

启动 Boost 线程时是否有任何内存保证?我在Java Language Specification 17.4.5 中寻找保证:

线程上的 start() 调用发生在已启动线程中的任何操作之前。

就我而言,我想创建一个(非线程安全的)TCP 客户端,然后启动一个接收器线程:

struct Connection {
    boost::shared_ptr<TcpClient> client;
};

auto client = boost::shared_ptr<TcpClient>{new TcpClient};
client->setTimeouts(60 * 1000, 60 * 1000);
client->connect(host, port);

auto connection = boost::shared_ptr<Connection>{new Connection};
connection->client = client;

auto receiverThread = boost::shared_ptr<thread>{new thread([&connection]() {
  // can I access the client safely?
  while (connection->client->isConnected()) {
    // do receiving stuff
  }
})};

是对client 的更改吗? e.超时,主机和端口,在启动的线程中可见吗?

【问题讨论】:

  • 有趣的问题。在实践中,可能是的,但我无法在 boost.js 中找到明确的保证。在 c++11 库中,发布/获取是一种保证。

标签: c++ windows boost boost-thread


【解决方案1】:

是的。该线程事先不存在,因此它不能具有“陈旧”值(例如在寄存器中)。 CreateThread 之前的所有写入对新线程都是可见的。

底层操作系统函数充当隐含的内存屏障(例如CreateThread)。

另见,例如:C++ - Should data passed to a thread be volatile?


旁注:考虑按值捕获connection 共享指针。这就是共享指针的全部意义,共享所有权。

【讨论】:

  • “底层操作系统函数充当隐含的内存屏障”。引用?
  • @n.m.虽然我还希望看到一些明确的文档,但我认为可以肯定地说CreateThread 在不包含至少一个内存屏障的情况下无法正确执行其功能。 (我想您可能会在假设的未来平台上遇到麻烦,在这些平台上,内存屏障仅适用于特定地址。)
  • @HarryJohnston 尽管这很有意义,但这对我来说并不是很明显,而且我找不到权威文档来说明这一点。 Synchronization and Multiprocessor Issues 页面有一个简短的列表“同步函数[使用适当的屏障来确保内存排序”,但CreateThread 不在其中。我希望这个答案能详细说明该声明并提供一些参考。
  • @dxiv,我的理由是调度程序必须将有关新线程的信息传递给将要运行它的核心,我无法想象在没有内存的情况下如何可靠地完成屏障。我同意这是一个不能令人满意的论点。我们确实知道线程条目是序列化的(请参阅 DllMain 的文档),如果此序列化是在关键部分完成的,那么这将确保按照您链接到的页面进行内存排序。
  • 不幸的是,我认为我们无法保证加载程序锁实际上是一个关键部分。就内存排序而言,它使用的任何同步原语可能相当于临界区,但这仍然是我的猜测。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 2016-09-06
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多