最近一个多月写的帖子比较杂,导致本系列又好久没更新了。结果又有网友在评论中催我了,搞得我有点囧。今天赶紧把多线程篇补上。上次聊操作系统
的时候,由于和OS有关的话题比较琐碎,杂七杂八说了一大堆。当时一看篇幅有点长,就把多进程和多线程的部分给留到后面了。<!-- program-think-->
★编译器
◇关于C运行库选项
先来说一个很基本的问题:关于C运行库(后面简称CRT:C Run-Time)的设置。本来不想聊这么低级的问题,但周围有好几个人都在这个地方吃过亏,所以还是讲一下。
大部分C++编译器都会自带有CRT(可能还不止一个)。某些编译器自带的CRT可能会根据线程的支持分为单线程CRT和多线程CRT两类。当你要进行多线程开发的时候,别忘了确保相关的C++工程项目使用的是多线程的CRT。否则会死得很难看。
尤其当你使用Visual C++创建工程项目,更加要小心。如果新建的工程项目是不含MFC的(包括Console工程和Win32工程),那工程的默认设置会是使用“单线程CRT”,如下图所示:
◇关于优化选项
“优化选项”是另一个很关键的编译器相关话题。有些编译器提供号称很牛X的优化选项,但是某些优化选项可能会有潜在的风险。编译器可能自作主张打乱执行指令的顺序,从而导致出乎意料的线程竞态问题(Race Condition,详细解释看“这里
”)。刘未鹏同学在“C++多线程内存模型
”里举了几个典型的例子,大伙儿可以去瞧一瞧。
建议只使用编译器常规的速度优化选项即可。其它那些花哨的优化选项,增加的效果未必明显,但是潜在的风险不小。实在不值得冒险。
以GCC为例:建议用-O2
选项即可(其实-O2
是一堆选项的集合),没必要冒险用-O3
(除非你有很充足的理由)。除了-O2
和-O3
之外,GCC还有一大坨(估计有上百个)其它的优化选项。如果你企图用当中的某个选项,一定要先把它的特性、可能的副作用都摸清楚,否则将来死都不知道怎么死的。
★线程库的选择
由于当前的C++ 03标准几乎没有涉及线程相关的内容(即使将来C++ 0x包含了线程的标准库,编译器厂商的支持在短期内也未必全面),所以在未来很长的一段时间,跨平台的多线程支持还是要依赖第三方库。所以线程库的选择是大大滴重要。下面大致介绍一下几个知名的跨平台线程库。
◇ACE
先说一下ACE这个历史悠久的库。如果你之前从未接触过它,先看“这里
”扫盲。从ACE的全称(Adaptive Communication Environment)来看,它应该是以“通讯”为主业。不过ACE对“多线程”这个副业的支持还是非常全面的,比如互斥锁(ACE_Mutex)、条件变量(ACE_Condition)、信号量(ACE_Semaphore)、栅栏(ACE_Barrier)、原子操作(ACE_Atomic_Op)等等。对某些类型比如ACE_Mutex还细分为线程读写锁(ACE_RW_Thread_Mutex)、线程递归锁(ACE_Recursive_Thread_Mutex)等等。
除了支持很全面,ACE还有另一个很明显的优点,就是对各种操作系统平台及其自带的编译器支持很好。包括一些老式的编译器(比如VC6),它也能够支持(此处所说的支持
,不光是能编译通过,而且要能稳定运行)。这个优点对于跨平台开发那是相当相当滴明显。
那缺点捏?由于ACE开工的年头很早(大概是上世纪九十年代中期),那会儿很多C++的老特性都还没出来(更别提新特性了),所以感觉ACE整个的风格比较老气,远不如boost那么时髦前卫。
◇boost::thread
boost::thread正好和ACE形成鲜明对照。这玩意貌似从boost
1.32版本开始引入,年头比ACE短。不过得益于boost里一帮大牛的支持,发展还是蛮快的。到目前的boost
1.38版本,也能够支持许多特性了(不过似乎没ACE多)。鉴于很多C++标准委员会的成员云集在boost社区中,随着时间的推
移,boost::thread终将成为C++线程的明日之星,前途无量啊!
boost::thread的缺点就是支持的编译器不够多,尤其是一些老式
编译器(很多boost的子库都有此问题,多半因为用了一些高级的模板语法)。这对于跨平台而言一个比较明显的问题。
◇wxWidgets
和QT
wxWidgets和QT都是GUI界面库,但是它们也都内置和对线程的支持。wxWidgets线程的简介可以看“这里
”,关于QT线程的简介可以看“这里
”。这两个库对线程的支持差不多,都提供了诸如mutex、condition、semaphore等常用的机制。不过特性没有ACE丰富。
◇如何权衡
对于开发GUI软件并已经用上了wxWidgets或者QT,那你可以直接用它们内置的线程库(前提是你只用到基本的线程功能)。由于它们内置的线程库,特性稍嫌单薄。万一你需要某高级的线程功能,那得考虑替换成boost::thread或ACE。
至于boost::thread和ACE的取舍,主要得看软件的需求了。如果你要支持的平台挺多挺杂,那建议选用ACE,以免碰上编译器不支持的问题。如果你只需要支持少数几个主流的平台(比如Windows、Linux、Mac),那建议用boost::thread。毕竟主流操作系统上的编译器,对boost的支持还是蛮好的。
★编程上的注意事项
其实多线程开发,需要注意的地方挺多的,我只能大致列几个印象比较深的注意事项。
◇关于volatile
说到多线程编程可能碰到的陷阱,那就不得不提到volatile
关键字。如果你对它还不甚了解,先看“这里
”扫盲一下。由于C++ 98和C++ 03标准都没有定义多线程的内存模型,而标准中也就volatile
和线程沾点儿边。结果导致C++社区中有相当多的口水都集中在volatile
身上(其中有不少C++大牛的口水)。有鉴于此,我这里就不再多啰嗦了。推荐几个大牛的文章:Andrei Alexandrescu
的文章“这里
”、还有Hans Boehm的文章“这里
”和“这里
”。大伙儿自个儿去拜读一下。
◇关于原子操作
有些同学光知道多个线程的竞争写
需要加锁,却不知道多个读
单个写
也需要保护。比如有某个整数int nCount = 0x01020304;在并发状态下,一个写线程去修改它的值nCount = 0x05060708;另一个读线程去获取该值。那么读线程有没有可能读取到一个“坏”的(比如0x05060304)数据捏?
数据是否坏掉,取决于对nCount的读和写是否属于原子操作。而这就依赖于很多硬件相关的因素了(包括CPU的类型、CPU的字长、内存对齐的字节数等)。在某些情况下,确实可能出现数据坏掉。
由于我们讨论的是跨平台的开发,天晓得将来你的代码会在啥样的硬件环境下执行。所以在处理类似问题的时候,还是要用第三方库提供的原子操作类/函数(比如ACE的Atomic_Op)来确保安全。
◇关于对象的析构
在之前的系列帖子“C++对象是怎么死的?
”里面,已经分别介绍了Win32平台和Posix平台下线程的非
自然死亡问题。由于上述几个跨平台的线程库底层还是要调用操作系统自带的线程API,所以大伙儿还是要尽最大努力确保所有
线程都能够自然死亡。
今天的话题就聊到这里,下一次聊多进程的话题。
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者编程随想
和本文原始地址:
http://program-think.blogspot.com/2009/04/cxx-cross-platform-develop-6-thread.html
分享到:
相关推荐
- 在C++中,这样的库可以帮助开发者编写无需关心底层操作系统差异的代码,提高代码的可移植性。 4. **testthreadpool.cpp**: - 这个文件很可能是线程池的测试程序,用于验证`threadpool.c`和`threadpool.h`的...
总之,C++跨平台开发是一项复杂但值得投入的任务,它不仅可以扩大应用的受众范围,还可以提高代码的重用率和开发效率。通过采用上述策略和技术,开发者可以有效地克服跨平台开发中的挑战,创建出高质量、高可移植性...
在C++编程中,线程和锁是并发编程的核心元素,尤其在开发跨平台的应用程序时,需要确保代码能够在不同的操作系统环境下正常运行。本项目提供了一个C++封装的线程类和锁类,使得开发者可以方便地在Linux和Windows平台...
C++ Qt6 跨平台开发是一项重要的技术,它允许开发者使用C++语言构建可以在多个操作系统上运行的应用程序,包括Windows、Linux、macOS、Android以及iOS等。Qt库提供了丰富的功能,涵盖了图形用户界面(GUI)、网络...
这些是进行跨平台开发的基础,因为它们确保代码的可移植性和复用性。 接下来,作者深入讨论了跨平台开发的关键问题,如处理操作系统差异、文件系统接口、线程与并发、网络编程以及图形用户界面(GUI)构建。在不同...
C和C++是两种广泛用于跨平台开发的语言,因为它们具有高度的灵活性和广泛的可移植性。以下是对这两个主题的详细阐述: 一、跨平台软件开发 跨平台软件开发是指编写一次代码,然后能够在多种操作系统(如Windows、...
综上所述,这个开源的win32平台C++多线程开发包提供了一个在Windows环境下编写多线程程序的解决方案,它基于C++语言和POSIX线程标准,通过`pthreadVC2.dll`和`pthreads`库实现了跨平台的线程功能。对于希望在Windows...
C++多线程是编程中一个重要的概念,它允许程序同时...这不仅提高了代码的可读性和可维护性,还简化了跨平台的移植工作。然而,编写多线程代码时仍需关注线程安全、资源管理和同步问题,以确保程序的正确性和高效性。
在C++11之前,实现多线程通常需要依赖平台特定的API,而C++11标准库提供了跨平台的多线程支持,让开发者能够更容易地编写出高效且可移植的多线程程序。 一、线程基础 1. `std::thread` 类:这是C++11中用于创建和...
该库可以满足不同平台上的多线程编程需求,提高了程序的可移植性和可靠性。 结论: 本论文设计和实现了一个统一的多线程库和定时器类库,abolished 了平台之间编程上的差异,提高了程序的可靠性和高效性。该论文的...
在C++编程中,跨平台性是一个重要的考量因素,特别是在涉及到操作系统底层机制如线程、锁和信号量等时。本文将深入探讨标题和描述中提及的“跨平台的C++线程模板类”以及“信号量及互斥量模板类”。 首先,线程是...
从C++的基础到深入的MacOS和Android开发,再到实现软件可移植性的策略,每一个部分都对理解和掌握跨平台开发的核心概念至关重要。通过深入学习这些内容,开发者可以拓宽自己的视野,提高代码复用性,降低维护成本,...
在IT行业中,嵌入式系统和物联网(IoT)领域的发展日新月异,而“基于嵌入式Linux的具有可移植性的C++程序开发框架”正是这些领域的重要工具之一。 Embedme,作为这样一个框架,旨在简化Linux应用程序的开发过程,...
标题和描述中提到的“跨平台的C++程序开发框架”通常是指能够在多种操作系统上运行的C++编程框架,如Windows、Linux、macOS等。这样的框架为开发者提供了统一的API,使得代码可以在不同的平台上无缝迁移,提高了软件...
此外,为了使VTimer更具可移植性,可能还采用了条件编译或预处理器指令(如`#ifdef`和`#endif`),来处理Windows和Linux之间的API差异。这样,同一段代码可以在两种操作系统下正确编译和运行。 总的来说,这个跨...
它支持多种操作系统和编译器,并且具有高度的可移植性。STLport的目标是提供一个与C++标准尽可能接近的实现,同时也兼容不同的编译器版本。例如,在早期的VC7.1版本中,由于该编译器对C++标准的支持不够完善,因此...
在C++编程中,跨平台性是一个重要的考量因素,尤其是当你需要在Windows和Linux等不同操作系统上运行同一段代码时。本示例着重讲解如何利用C++标准库中的互斥锁(mutex)和条件变量(condition variable)进行线程...
- **可移植性**:由于C++标准库没有内置的日志机制,跨平台的日志类通常需要处理不同操作系统上的I/O差异。这个"log"类应该能够在Windows、Linux、macOS等操作系统上工作。 - **灵活性**:日志类应提供不同的日志...
C++是一种强大而灵活的面向对象编程语言,而Qt则是一个功能丰富的开源跨平台开发框架,它为C++提供了丰富的库和工具,使得开发高质量、可移植的应用程序变得更加便捷。本文将深入探讨如何在C++中利用Qt框架实现设计...