C++ Asio异步和并发

C++ Asio异步和并发,c++,boost-asio,C++,Boost Asio,我正在用boost asio编写一些代码,使用异步tcp连接。我得承认我对此有些怀疑。所有这些都涉及到并发性。以下是一些: 如果我在同一个套接字上启动两个或多个async_write而不等待第一个套接字的完成,会发生什么?处理程序(和异步写入)会重叠还是asio提供序列化和同步 上述问题与异步连接和异步读取相同。一般来说,从不同的线程调用这些函数是安全的(我不是说使用不同的缓冲区,这是另一个问题…) 如果在同一个套接字上启动两个异步操作,它们可能以任意顺序发生。只要它们使用不同的缓冲区,它

我正在用boost asio编写一些代码,使用异步tcp连接。我得承认我对此有些怀疑。所有这些都涉及到并发性。以下是一些:

  • 如果我在同一个套接字上启动两个或多个async_write而不等待第一个套接字的完成,会发生什么?处理程序(和异步写入)会重叠还是asio提供序列化和同步

    • 上述问题与异步连接和异步读取相同。一般来说,从不同的线程调用这些函数是安全的(我不是说使用不同的缓冲区,这是另一个问题…)

如果在同一个套接字上启动两个异步操作,它们可能以任意顺序发生。只要它们使用不同的缓冲区,它就“安全”,因为它不会崩溃,但这种行为几乎从来都不是您想要的。

我从您的问题中假设您有一个io_服务实例,并且您希望从多个线程对其调用asyncwrite()

asyncwrite()最终调用ioservice的post()方法,该方法反过来获取锁并将要写入的位推送到工作队列中,从而确保不会交错写入位。这些位最终会被写出来,而保存它们的底层数据结构(一个字符数组或任何东西)必须保持有效,直到您得到表示写操作已完成的回调为止。如果您使用与完成处理程序完全相同的回调函数,您将无法知道两次写入中的哪一次导致调用该函数,并且如果该函数执行任何不线程安全的操作,则行为可能未定义或不正确。处理这种情况的一种常用方法是使用一个作为完成处理程序的结构实例(只需重载()运算符):您可以设置结构的属性以指示它对应的写入,然后在调用完成处理程序时参考这些值

但是,如果没有共享锁,就无法控制哪个线程实际执行其asyncwrite方法。事实上,即使启动两个线程,其中一个线程立即调用asyncwrite,另一个线程睡眠一个小时,然后调用asyncwrite,您仍然不能确定操作系统没有愚蠢地调度线程并首先执行第二个线程的调用。(这个例子是病态的,但这一点普遍有效。)

同样的情况也适用于异步读取。您当然可以交错调用(即在调用完成处理程序之前先执行一个异步读取,然后执行另一个异步读取),但无法保证将按照您希望的顺序执行,而无需一些外部手段来确保这一点