混合 C++11 std::thread 和 C 系统线程(即 pthreads)

Posted

技术标签:

【中文标题】混合 C++11 std::thread 和 C 系统线程(即 pthreads)【英文标题】:Mixing C++11 std::thread and C system threads (ie pthreads) 【发布时间】:2012-09-18 19:10:02 【问题描述】:

我正在编写一个多线程 C++ 程序并希望使用多线程 C 库。 这个库希望我使用本机系统方法为其创建一些工作线程,并使用如下代码将控制权传递给它的 run() 函数:

void system_specific_thread_init();
#ifdef _WIN32
    DWORD WINAPI system_specific_thread_run( LPVOID unused )
    
        library_run();
        return 0;
    

    void system_specific_thread_init()
    
        Createthread(NULL, 0, system_specific_thread_run, NULL, 0, NULL);
    
#else
    void* system_specific_thread_run(void *unused)
    
        library_run();
        return NULL;
    

    void system_specific_thread_init()
    
        pthread_t id;
        pthread_create(&id, NULL, system_specific_thread_run, NULL);
    
#endif
system_specific_thread_init();

之后它将使用相关的本机系统互斥方法对其他本机系统线程调用其函数,同时继续进行是自己的工作。

但是,我使用 C++11 <thread> 库来创建和管理我的所有线程。我希望使用std::thread(library_run) 创建工作线程并从其他此类线程调用库函数。

这样做安全吗,还是 DS9K 会导致恶魔从我的鼻子里飞出?

【问题讨论】:

【参考方案1】:

C++11 线程可能有也可能没有名为native_handle() 的成员函数;它是否存在由实现定义。如果存在,则返回native_handle_type 类型的对象;它是由实现定义的,这种类型的对象可以用于什么。所以请阅读您的文档。

【讨论】:

我看不出这个答案与所提出的问题有什么关系——如果 C 库只需要使用系统互斥锁,那么就不需要获取本机线程句柄。 @Pete 你能详细说明你的答案吗? @LexiR - 我很抱歉; @cmeerw 是正确的——我的回答虽然在技术上是正确的,但并没有真正解决你的问题。通常,互斥锁不依赖于线程细节,因此使用本机互斥锁可能没问题。另一方面,如果您使用 std::mutex(连同 std::lock_guard),您将获得异常安全的锁定和解锁,以及我上面描述的相同的 native_handle 舞蹈,可能会进入系统互斥体。跨度> 【参考方案2】:

C++ 标准没有指定 C++ 线程如何与任何其他线程库交互,但总的来说,我希望 C++ 实现使用底层系统线程库,因此您的使用应该是安全的。

能够使用使用系统线程库锁定原语的第三方库是一个非常常见的用例,它应该可以正常工作(否则 C++ 线程支持在许多实际情况下几乎毫无用处) .正如 Pete 指出的那样,任何涉及线程句柄/id 的事情都可能更加棘手(但阅读您的问题时不应该要求这样做)。

【讨论】:

【参考方案3】:

这取决于图书馆实际在做什么。使用pthreads 进行静音等应该不是问题。但是,如果库实际上尝试使用 pthread_join 之类的函数来管理线程,则可能会导致问题。它可能仍然适用于以pthread 为标准的系统(unix 等),因为std::thread 可以实现为围绕pthreads 的非常薄的包装器,但这显然非常依赖于实现,而不是我会计算的东西甚至可以为同一编译器的未来版本工作。 CreateThread 的用法也可以进行类似的论证。

【讨论】:

【参考方案4】:

新的 C 和 C++ 标准(C11 和 C++11)都实现了相同的线程模型,并且它们的接口应该兼容。因此,无论平台为您提供 C++11 线程的实现,都应该能够在 C 中为您提供相同的实现。如果不能,那肯定只是暂时的。

如果您所在的平台将 pthread 作为本机线程模型(可能是 POSIX 平台),那么 C++11 线程几乎肯定是在它之上构建的。但请注意,这两种线程模型之间的调用约定只是相似,而不是相等。例如,线程函数的返回值对于 pthread 是 void*,对于 C++11/C11 是 int

但是,如果您赶时间,并且迫不及待地希望您的编译器供应商也提供 C11 接口,您可以自己围绕 C++ 函数实现浅接口。这样做应该没什么大不了的。

【讨论】:

【参考方案5】:

这样做是否安全,或者 DS9K 会导致恶魔飞出我的 鼻子?

我不会将它用于任务关键型软件。 在 std::thread 上尝试 WinApi 调用 FreeLibraryAndExitThread 后,它退出了线程但没有释放 dll。 (它与 CreateThread 一起工作)

【讨论】:

以上是关于混合 C++11 std::thread 和 C 系统线程(即 pthreads)的主要内容,如果未能解决你的问题,请参考以下文章

来自 c++11 的 std::thread 问题

c++11的std::thread能用类的成员函数构造一个线程吗?语法怎样?

C++11 std::thread 和虚函数绑定

在 C++11 中通过引用 std::thread 传递对象

C++ 11 std::thread 循环

使用 c++11 std::thread 获取段错误