当使用两个线程发送和接收时,如何避免数据竞争asio::ip::tcp::iostream?
我正在编写一个使用asio::ip::tcp::iostream输入和输出的程序.程序通过端口5555接受来自(远程)用户的命令,并通过相同的TCP连接将消息发送给用户.因为这些事件(从用户接收的命令或发送给用户的消息)是异步发生的,所以我有单独的发送和接收线程.
在这个玩具版本中,命令是"一个","两个"和"退出".当然"退出"退出该计划.其他命令不执行任何操作,任何无法识别的命令都会导致服务器关闭TCP连接.
传输的消息是简单的序列编号消息,每秒发送一次.
在这个玩具版本和我正在尝试编写的实际代码中,发送和接收进程都使用阻塞IO,因此似乎没有一种使用std::mutex其他同步机制的好方法.(在我的尝试中,一个进程会获取互斥锁然后阻塞,这对此无效.)
为了构建和测试它,我在64位Linux机器上使用gcc版本7.2.1和valgrind 3.13.建立:
g++ -DASIO_STANDALONE -Wall -Wextra -pedantic -std=c++14 concurrent.cpp -o concurrent -lpthread
Run Code Online (Sandbox Code Playgroud)
要测试,我使用以下命令运行服务器:
valgrind --tool=helgrind --log-file=helgrind.txt ./concurrent
Run Code Online (Sandbox Code Playgroud)
然后我telnet 127.0.0.1 5555在另一个窗口中使用来创建与服务器的连接.什么helgrind正确地指出的是,有一个数据竞争,因为两者runTx并runRx试图以异步方式访问相同的数据流:
== 16188 ==线程#1在0x1FFEFFF1CC读取大小1期间可能发生数据竞争
== 16188 ==持有的锁:无
...更多的线路被省略了
#include <asio.hpp>
#include <iostream>
#include <fstream>
#include <thread>
#include <array>
#include <chrono>
class Console {
public:
Console() :
want_quit{false},
want_reset{false}
{}
bool getQuitValue() const { return want_quit; }
int run(std::istream …Run Code Online (Sandbox Code Playgroud)