C ++ / Thrift:TThreadedServer :: stop()线程安全吗?

时间:2018-12-24 21:38:10

标签: c++ multithreading c++11 rpc thrift

我想在单独的线程中使用TTheadedServer来控制何时停止/启动它。我的应用程序仅需要1个控制线程和1个处理线程。我不希望有一个以上的客户端,因为我正在使用节俭作为中继。 TSimpleServer不是线程安全的,因此我放弃了该选项。

我做了一个最小的例子来检查它是否是线程安全的,并使用clang的线程清理器来确保它是线程安全的。这是例子

std::shared_ptr<MyHandler> handler = std::make_shared<MyHandler>();

int port = 9090;

th::stdcxx::shared_ptr<th::TProcessor>         processor(new HandlerProcessor(handler));
th::stdcxx::shared_ptr<tht::TServerTransport>  serverTransport(new tht::TServerSocket(port));
th::stdcxx::shared_ptr<tht::TTransportFactory> transportFactory(
    new tht::TBufferedTransportFactory());
th::stdcxx::shared_ptr<thp::TProtocolFactory> protocolFactory(new thp::TBinaryProtocolFactory());

ths::TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);

// start in another thread
std::thread          t(&ths::TThreadedServer::serve, &server);
t.detach();

std::this_thread::sleep_for(std::chrono::seconds(5));

// stop in this thread
server.stop();

std::this_thread::sleep_for(std::chrono::seconds(5));

所以我要做的只是在另一个线程中用serve()启动服务器,然后等待一段时间,然后停止它。我使用线程清洁剂运行了此操作,并收到了一些线程安全警告。我在这里提到2:

首先:thrift/lib/cpp/src/thrift/transport/TServerSocket.cpp:244,在:

interruptableChildren_ = enable;

第二个:thrift/lib/cpp/src/thrift/transport/TServerSocket.cpp:654,在:

if (-1 == send(notifySocket, cast_sockopt(&byte), sizeof(int8_t), 0)) {
  GlobalOutput.perror("TServerSocket::notify() send() ", THRIFT_GET_SOCKET_ERROR);
}

那么我在做什么正确? TThreadedServer控制器线程安全吗?尽管测试程序可以正常工作,但线程清理程序似乎并不这么认为。

我正在使用Thrift 0.12.0。

1 个答案:

答案 0 :(得分:0)

它是线程安全的,但它可能具有多线程错误,这些错误在实践中永远不会出现。例如,在interruptableChildren_的情况下,流程是您可以在主线程中配置其值,但随后由接受线程(运行TServerSocket::acceptImpl的线程)读取它的值。理论上,您从不受保护的变量中进行写入和读取。实际上,使用     std::thread t(&ths::TThreadedServer::serve, &server); 行,因此不会发生数据争用。

我猜测notify()的情况与此相似。