C++11 std::thread vs windows CreateThread
哪个选项更适合在Visual C ++下创建(和管理)线程:C ++ 11 std::thread或WinAPI函数(例如CreateThread,_beginthreadex等),为什么?
-
std::thread更好,因为它是标准且可移植的
-
std::thread使您可以编写跨平台应用程序。而且,如果仍然需要使用通过此API创建的线程来执行特定于平台的操作,则可以通过native_handle获取实现句柄,并将其传递给特定于平台的函数。
-
请注意,在Windows上,不应使用CreateThread,而应使用_beginthreadex,以便正确初始化CRT线程本地存储。 std::thread是C ++ 11的实现方法,在Microsoft平台上,它使用ConCRT / ppl。 std::thread具有可用于Windows Store应用程序的优势,在该应用程序中其他线程API在那里不可用。
-
@ChuckWalbourn:CreateThread确实不再是问题,除了在少数情况下(最明显的是如果应用程序必须在内存或地址空间严重不足时必须应付)。在正常情况下,CRT会根据需要即时初始化其存储。
-
FWIW,std::unique_ptr使带有CreateThread的RAII成为可能-使用CloseHandle作为删除器功能。
-
定义"更好"(或者,您有兴趣从中进行评估的立场)或这是"基于观点的"。
可移植性
std::thread是C ++ 11标准的新功能-使用它,您可以跨支持C ++ 11的编译器以C ++编写可移植代码。您可以在其中感觉到future。
它基于boost::thread,后者支持不支持C ++ 11的较旧的编译器,这使得向其他平台的移植更加容易。
如果您需要使用平台特定的技巧,则可以使用std::thread::native_handle。
CreateThread特定于WinAPI,这意味着编写不可移植的代码。而且,此API相当旧,使用起来更加不便。
区域情报研究所
WinAPI是一种C API,不鼓励使用现代C ++良好实践。您创建的每个线程原语,都必须稍后手动销毁。
C ++ 11中的线程库不是这种情况,这使得更高级的抽象更易于编写。尽管std::thread仍处于较低级别(您的线程为.join()或.detach(),或者线程析构函数将终止您的程序),但C ++ 11线程库具有std::lock_guard和其他用于支持RAII的锁类用于互斥。
尽管C ++ 11具有一些更高级别的抽象,例如std::async用于异步启动函数,但它不提供其他抽象,例如线程池,因此您可能要使用其他库。
类型安全
WinAPI只能调用具有特定签名的函数指针-容易出现与类型安全,对象生存期和内存管理不当相关的错误。
std::thread可以调用任何可调用对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| // call free-standing function in a separate thread
std::thread first(func);
// call free-standing function with arguments (1, 2), in a separate thread
std::thread second(func, 1, 2);
// call static member function in a separate thread
std::thread third(&A::static_memfun);
// call non-static member of a temporary in a separate thread
std::thread fourth(&A::memfun, A());
//call std::function in a separate thread
std::function<void(int)> callback = std::bind(func, 1, _1);
std::thread fifth(callback, 2);
// call a function object
Functor f;
std::thread sixth(f); |
TL; DR:在新的C ++代码中没有理由使用WinAPI线程作为主要的线程机制。
-
感觉future,哈哈。
-
@Quentin和经验broken_promise s
-
还要记住,使用std::thread代替CreateThread会显着增加程序的内存使用量和可执行文件的大小,具体取决于多个因素,例如创建的线程数量,静态与动态链接以及编译优化。
-
@GetFree [需要引用]
-
@milleniumbug,当我决定尝试新的C ++线程时,我已经在自己的项目中看到了它。您需要做的就是将您的CreateThread调用替换为std::thread var(...),它将立即生效。然后,只需将结果与您的旧可执行文件进行比较即可。
跨平台是一个小好处。真正的好处在于界面。 std::thread提供关于线程清理的RAII保证,并且支持任意函数对象参数,而不仅仅是函数指针。 std::thread是CreateThreadEX上的C ++ 11包装,这是有原因的。
恰如其分,std :: thread是一个糟糕的API。如果您自己创建线程,则可能做错了。使用真正的线程API,例如Intel的TBB或Microsoft的PPL,它们远远优于可怕的std::thread,甚至使CreateThreadEx更糟。 std::thread就像是,"嘿,我为您提供了跨平台的mmap,因此您可以在上面编写自己的malloc,请尽情享受!"。
-
好吧,我宁愿在mmap之上创建自己的malloc,而不是只拥有malloc并尝试在其上砍一个mmap。处于低水平并不可怕。没有低级的东西,我们将永远不会拥有高级的功能
-
@youdontneedtothankme:是的。除了几乎没有人可以真正在std::thread之上正确地实现线程抽象,并且只有实现者需要std::thread而不是用户。
-
std::thread甚至都不是RAII类(至少不是经典意义上的类):它的析构函数不会清理线程-它将终止程序。
您可能应该使用std :: thread。
std :: thread是(新)标准的一部分,并且可移植。
除非您只针对Windows,并且需要使用WinAPI与线程进行交互,否则std :: thread是必经之路。