【发布时间】:2015-11-10 22:57:35
【问题描述】:
boost::shared_ptr<A> a = boost::shared_ptr<A>(new A);
a->i = 2;
strand.post([a](){assert(a->i == 2)});
或
io_service.post([a](){assert(a->i == 2)});
当我在 thread1 中向 strand 或 io_service 发布处理程序时,执行处理程序的 thread2 是否在发布之前看到数据更改?
Java 也有类似的 Executor 来建立前发生关系:
在提交 Runnable 之前线程中的操作 执行者发生-在其执行开始之前。同样适用于可调用对象 提交给 ExecutorService。
asio 呢?
请注意,此问题不询问已发布到 io_service 或 strand 的处理程序的执行顺序。 Asio doc 表示如果使用 strand,则 post(a) 发生在 post(b) 之前。但是这个问题问:(编码顺序)post(a)之前的动作是否发生在post(a)之前(处理程序a的执行)?这是关于内存模型的。让我澄清一下:
// in thread1
global variable a = 111;
start a new thread2 which will access global variable a
我们知道线程 1 中的动作在线程 2 开始之前发生在线程 2 开始之前。这意味着: 1、最终执行顺序与代码顺序相同(编译器或CPU不会改变顺序)。 2、global variable a值设置动作将刷新到主内存(或同步到thread2的CPU缓存),然后thread2将更新为global variable a的最新值(当然,直到它开始)。
asio 的帖子与这个例子类似,所以我问了这个问题。我认为 asio 的帖子应该先发生关系,否则它将毫无用处。但我不确定,我想知道 asio 是怎么做到的。
要让happen-before,有3种方式:1、线程启动、加入。 2、锁定和解锁互斥量。 3、内存屏障。
【问题讨论】:
-
让我们澄清一下:您认为
a->i = 2;可能会在strand.post之后执行? -
是的。但是还有其他情况:执行顺序和代码顺序一样,但是thread2读不到a->i的最新值集。如果没有发生之前的关系,它们都可能发生
-
请注意,如果您正确使用链,则帖子“来自同一链”,因此整个流程就像单线程顺序一样
-
@sehe 我不认为这是一个骗局。您引用的问题与函数调用的顺序有关,但这个问题与内存访问的顺序有关。答案将取决于内存模型以及
post()是否具有隐式释放语义以及仿函数调用是否具有隐式获取语义。我的猜测是肯定的,但我不知道这是否在任何地方都有说明;它可能只是内部线程安全队列 @987654331@ 包含的副作用。
标签: c++ concurrency boost-asio