使用异步 API 更改反应器的状态是否安全,而无需手动同步?



我将gRPC与异步API结合使用。这需要基于ClientBidiReactor或ServerBidiReactor 等类构建反应器

如果我理解正确的话,gRPC的工作原理是这样的:它从一些线程池中获取线程,并使用这些线程执行正在使用的反应器的某些方法。

问题

现在,问题是反应堆何时进入状态。我知道单个反应器的方法很可能会按顺序执行,但它们可能从不同的线程运行,这是正确的吗?如果是这样的话,那么我们是否有可能遇到这里描述的问题?

长话短说,如果在这种情况下我们有一个未同步的状态,是否有可能一个线程会更新状态,然后来自反应器的下一个方法将从另一个线程执行,它将看到未更新的值,因为该状态的新值尚未刷新到主内存?

老实说,我对此有点困惑。在这里和这里的grpc示例中,这似乎没有得到解决(互斥对象用于不同的目的,并且值不是原子的(。

我使用/链接了bidi反应器的例子,但这指的是所有类型的反应器。

结论/问题

在这一点上,我基本上有几个问题:

  • 这里的担忧有效吗?我是否正确理解了一切,还是遗漏了什么?问题存在吗
  • 我们需要手动同步反应堆的状态吗?还是由库以某种方式处理(我的意思是处理对主内存的刷新(
  • 图书馆的作者知道这一点吗?他们在编写我链接的示例时是否牢记这一点

提前感谢您的帮助,祝您一切顺利!

你说得对,这些例子并没有很好地展示这一点,还有一些改进的空间。操作完成反应方法(OnReadInitialMetadataDoneOnReadDoneOnWriteDone…(可以从gRPC库所拥有的不同线程并发调用,因此,如果您的代码访问任何共享状态,您将希望自己协调(通过同步、免锁类型等(。在实践中,我不确定这种情况发生的频率,也不确定哪些回调更可能重叠。

最初的回调API规范在;线程安全性";子句:L67:C++基于回调的异步API。在回调实现代码本身的几个地方也重申了这一点——例如,client_callback.h#L234-236。