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提交Runnable之前的一个线程中的操作 执行程序在执行开始之前发生。同样适用于Callables 提交给ExecutorService。
asio怎么样?
请注意,此问题不会询问已发布到io_service或strand的处理程序的执行顺序。 Asio doc说如果使用strand,post(a)发生在post(b)之前。但是这个问题问:在(a)发布之前(编码顺序)之前的动作是否发生在(a)之后(处理程序执行)?这是关于内存模型。让我澄清一下:
// in thread1
global variable a = 111;
start a new thread2 which will access global variable a
我们知道在thread2启动之前启动thread2之前thread1中的操作。这意味着:1,最终执行顺序与代码顺序相同(编译器或CPU不会更改顺序)。 2,global variable a
值设置操作将刷新到主内存(或同步到thread2的CPU缓存),然后thread2将更新为最新值global variable a
(当然,直到它开始)。
asio的帖子与这个例子类似,所以我问这个问题。我认为asio的帖子应该在关系之前发生,否则它将毫无用处。但我不确定,我想知道asio是如何做到的。
要发生之前,有3种方式:1,线程开始,加入。 2,锁定和解锁互斥锁。 3,记忆障碍。
答案 0 :(得分:0)
以下所有内容都与内存排序有关:io_service::post()
,io_service::dispatch()
,strand::post()
和strand::dispatch()
。这主要是io_service
和strand
的结果,它提供了可以同时使用单个对象的有力保证。在这种情况下,不需要潜在的阻塞同步,例如当dispatch()
发布到dispatch()
的处理程序可以在<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
函数的上下文中执行时,则会发出full memory fence。
documentation注意到使用内存屏障进行处理程序分配:
[...]如果需要从不同的线程调用分配函数,实现将插入适当的内存屏障以确保正确的内存可见性。