解除线程与另一个线程的阻塞

时间:2019-03-10 19:55:50

标签: c++ multithreading pthreads

我正在寻找一种在同时从网络接收数据的同时能够向终端输入数据的方法。

为此,我创建了一个新线程dataCapturestd::thread),该线程将使用std::cin获取输入。主线程是接收器。

当网络发送字符串“ end”时,程序需要退出。

这是简化的代码:

void dataCapture()
    while (! quit) {
        std::string data;
        std::cout << "Enter data: ";
        std::cin >> data;
    }
}

bool quit=false;

int main() {
    // socket creation
    // connection to server
    const std::string quit_value = "end";


    std::thread datacapture_T(dataCapture);

    while (! quit) {
        char recep[1024];
        recv(sd, recep, sizeof(recep),0);
        if (recep == quit_value) {
            quit=true;
        }
    }
    datacapture_T.join();
    return 0;
}

那是行不通的,因为在收到"end"之后,maindatacapture_T.join()上被阻止,因为dataCapturestd::cin调用中被阻止了。

是否可以从主线程取消阻止dataCapture线程?

如果不是,可以强行杀死它吗?

ps:我没有提供用于简化的锁。

我们非常感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

您可以使用std::cin关闭ctrl-z

解决此问题的另一种方法是进入dataCapture(),并通过执行quit_value在其中检查break

编辑:也考虑使用atomic来保持对定义好的并发线程的读写。不要以为它会增加太多的复杂性

答案 1 :(得分:0)

从理论上和实践上,都没有一种干净的方法可以通过编程方式杀死线程。

以编程方式解除阻塞和关闭线程(等待任何类型的输入)的标准方法是使用select()pipe()

  • 创建一个pipe()。
  • select()创建一个文件描述符集,其中包含您的输入文件描述符以及read()pipe()的文件描述符。
  • 代替对cin进行阻塞读取,而对select()进行阻塞调用。
  • 如果select()告诉您pipe()有什么要读的内容,请退出线程。由于在线程中检测到终止请求,因此可以清理所有资源并完成所有处理。这是关键。
  • 如果select()告诉您从cin读取一些内容,请对其进行读取和处理。
  • 从任何其他线程,例如在main()的末尾:
    • 只要您想终止线程,就将一个字节(值无关紧要)写入pipe()
    • join()线程。

您认为此方法听起来是任意和复杂的吗?它是!然而,这是很常见的做法,因为许多框架和程序都在使用它,所以您可以依靠它来工作。

还有一些较不理想的选择,例如轮询输入(非阻塞)和检查停止标志。也许最有用的替代方法是根本不使用任何其他线程来获取输入,并且对所有I / O使用单线程事件驱动的系统,而仅在其他线程中进行内部处理。

线程不是实现I / O并发的有用机制。线程对于创建CPU处理并发很有用。