我应该使用来自C++标准还是Windows API的条件变量?

6
当在Win32 C++程序中实现条件变量时,使用Win32函数、类和数据类型(例如CreateThreadSleepConditionVariableCSWaitForSingleObjectExReleaseMutexCONDITION_VARIABLE)还是C++11标准库中的函数、类和数据类型(例如threadwaitjoinunlockcondition_variable)更好呢?
由于这个问题的答案可能不是二元的,所以在做出这样的决定时应该考虑什么因素?

3
考虑到Visual Studio尚未完全实现标准,如果可移植性不是问题,建议目前使用Windows调用。 - woolstar
函数具有前置条件和后置条件。当您编写软件时,您有“目的”。函数可能满足您的目的,也可能不满足,但它们并不是“更好”或“更差”。它们只是函数。 - Daniel Daranas
@woolstar 我实际上正在使用Code::Blocks和最新版本的MinGW,但这是一个很好的考虑。 - Cerran
@DanielDaranas 正确。这是我在问题的最后一句话中已经提到的一个观点。我不知道这两组函数可能具有什么潜在的好处。 - Cerran
1
在某些情况下,无法进行一对一的比较。例如,CreateEvent()可以使用std::condition_variable复制,但底层实现有足够的不同,因此在尝试使用这些构造时可能会有性能差异。 - Chad
显示剩余2条评论
2个回答

6

C++同步机制是按照C++原则设计的。它们在析构函数中释放资源,并使用RAII确保安全锁定。它们使用异常来信号错误。

基本上,它们比基于函数的本机Windows API更难以不正确地使用。这意味着如果您可以使用它们(您的实现支持它们),您应该始终使用它们。

哦,它们也跨平台。


我完全同意。如果您需要这些对象的本地句柄,请使用native_handle()方法,但要理解本地句柄可能并不总是可用的,或者可能不是您想象的那样。例如,在C++11库实现中,互斥锁可能对于无争用情况使用原子变量,因此除非互斥锁有争用,否则将不会为任何内容提供本地句柄。 - Kuba hasn't forgotten Monica
1
旁注:VC2012 的线程库实现还有不少漏洞,可能会导致丑陋的竞争条件问题。因此,除非您已经在使用 VC2013,否则建议使用 Boost 的线程库实现代替(http://www.boost.org/doc/libs/1_55_0/doc/html/thread.html)。 Boost 更加成熟稳定。两种实现在性能上没有区别,因为它们都是原生 Win32 函数的简单封装。 - ComicSansMS
如果程序已经包含其他Win32代码,那么它们是否跨平台并不重要,对吧?除非代码的某些部分可能被重新用于可移植代码。当然,我学习其中一种语言的优势在于所获得的知识可以跨平台使用。 - Cerran
是的。如果你学会了跨平台编码,你可以重用那些跨平台的部分,如果你想要移植的话,就会减少工作量。 - Sebastian Redl
经过进一步的研究并实现了自己的条件变量后,我现在明白了在C++标准库类中使用RAII和异常(如threadmutexcondition_variable)是相当不错的,并且使得处理错误比Win32函数更简单。此外,一旦你理解了这些类,它们就非常容易使用。 - Cerran

1
考虑到编译器的处理能力,这是一个需要注意的问题。例如,在Windows上安装MinGW时,你可以选择是否安装POSIX线程或Win32线程的API。另一方面,如果你使用TDM-GCC,请注意版本4.7.1及以下使用Win32线程,而版本4.8.1及以上使用POSIX线程。正如woolstar在上面提到的,如果你使用Microsoft的编译器,你应该检查它对这些类的支持中是否已解决了错误。
如果你的编译器支持POSIX线程,你可以使用C++标准库的线程类(例如threadmutexcondition_variable)。如果你的编译器支持Win32线程,你可以使用Win32线程函数。
在我的情况下,我最初使用的是TDM-GCC 4.7.1,并尝试使用C++标准库的类,但那并没有起作用(原因如上所述)。所以我单独安装了MinGW,并在安装程序的“线程”选项中选择了“posix”。然后我就能够使用那些类了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接