《C++多线程编程实战》——1.3 程序结构、执行流和运行时对象

但是,C++学起来并不轻松。有时,你会认为这是一门高深莫测、难以捉摸的语言,一门永远学不完也无法完全理解和掌握的语言。别担心,学习一门语言并不是要掌握它的所有细枝末节,关键要学会如何正确地用语言特性解决特定的问题。实践是最好的老师,根据具体情况尽可能多地使用相应的特性,有助于加深理解。

在给出示例前,我们先介绍一下查尔斯·西蒙尼的匈牙利表示法。他在1977年的博士论文中,使用元编程(Meta-Programming)(一种软件生产方法)在程序设计中制定了标准的表示法。文中规定类型或变量的第1个字母表示数据类型。例如,如果要给一个类命名,Test数据类型应该是CTest。第1个字母C表示Test是一个类。这个方法很不错,因为不熟悉Test数据类型的程序员会马上明白Test是一个类名。基本数据类型也可以这样处理,以int和double为例,iCount表示一个int类型的变量Count,而dValues表示一个double类型的变量Value。有了这些前缀,即使不熟悉代码也很容易识别它们的类型,提高了代码的可读性。

准备就绪
确定安装并运行了Visual Studio(VS)。

操作步骤
根据以下步骤创建我们的第1个程序示例。

1.创建一个默认的C++控制台应用程序[1],命名为TestDemo

2.打开TestDemo.cpp

3.输入下面的代码:

#include "stdafx.h"
#include <iostream>

using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
  cout << "Hello world" << endl;
  return 0;
}```
示例分析
不同的编程技术使得C++程序的结构多种多样。绝大多数程序都必须有``#include`或预处理指令。

`#inlude <iostream>`告诉编译器包含`iostream.`h头文件,该头文件中有许多函数原型。这也意味着函数实现以及相关的库都要放进可执行文件中。因此,如果要使用某个API或函数,就要包含相应的头文件,必要时还必须添加包含API或函数实现的输入库。另外,要注意<header>和"header"的区别。前者`(< >`)表示从解决方案配置的项目路径开始搜索,而后者(`""`)表示从与C++项目相关的当前文件夹开始搜索。

`using``命令指示编译器要使用std名称空间。名称空间中包含对象声明和函数实现,有非常重要的用途。在包含第三方库时,名称空间能最大程度地减少两个不同软件包中同名函数的歧义。

我们需要实现一个程序的入口点:`main`函数。前面提到过, ANSI签名用`main`, Unicode签名用`wmain`,编译器根据项目属性页的预处理器定义确定签名用`_tmain`。对于控制台应用程序,main函数有以下4种不同的原型:

int _tmain(int argc, TCHAR* argv[])
void _tmain(int argc, TCHAR* argv[])
int _tmain(void)
void _tmain(void)`
第1种原型有两个参数:argcargv。第1个参数argc(即,参数计数)表示第2个参数argv(即,参数值)中的参数个数。形参argv是一个字符串数组,其中的每个字符串都代表一个命令行参数。argv中的第1个字符串一定是当前程序的名称。第2种原型和第1种原型的参数类型、参数个数相同,但是返回类型不同。这说明main函数可能返回值,也可能不返回值。该值将被返回给操作系统。第3种原型没有参数,并返回一个整型值。第4种原型既没有参数也没有返回类型。看来,用第1种原型作为练习很不错。

函数体中的第1条语句使用了cout对象。cout是C++中标准输出流的名称。整条语句的意思是:把一系列字符(该例中是Hello world字符序列)插入标准输出流(通常对应的是屏幕)。

cout对象声明在std名称空间的iostream标准文件中。因此,要是用该对象必须包含相应的头文件,并且在_tmain函数前面先声明其所属的名称空间。

在我们使用的原型中(int _tmain(int, _TCHAR*)),_tmain返回一个整数。因此,必须在return关键字后面指定相应的int类型值,本例中是0。向操作系统返回值时,0通常表示执行成功。但是,具体的值由操作系统决定。

这个小程序非常简单。我们以此为例解释main`例程作为每个C++程序入口点的基本结构和用法。

单线程程序按顺序逐行执行。因此,如果把所有的代码都写成一个线程,这样的程序对用户并不友好。

如图1.1所示,应用程序要等用户输入数据后,才能重新获得控制权继续执行。为此,可以创建并发线程来处理用户的输入。这样,应用程序随时都能响应,不会在等待用户输入时毫无反应了。线程处理完自己的任务后,可以给应用程序发信号,告诉程序用户已完成相应操作。

图1.1 单线程程序按顺序逐行执行

更多讨论
每次我们要在主执行流中单独执行一个操作,都必须考虑使用一个单独的线程。最简单的例子是,实现一边计算一边在进度条上反映计算的进度。想在同一个线程中处理计算和更新进度条,可能行不通。因为如果一个线程既要进行计算又要更新UI,就不能充分地与操作系统绘画交互。因此,一般情况下我们总是把UI线程与其他工作线程分开。

来看下面的例子。假设我们创建了一个用于计算的函数(如,计算指定角度的正弦值或余弦值),我们要同步显示计算过程的进度:

void CalculateSomething(int iCount)
{
  int iCounter = 0;
  while (iCounter++ < iCount)
  {
    // 计算部分
    // 更新进度条部分
  }
}```
由于while循环的每次迭代都忙于依次执行语句,操作系统没有所需的时间逐步更新用户接口(该例中,用户接口指进度条),因此用户见到的可能是空的进度条。待该函数返回后,才会出现已经完全被填满的进度条。出现这种情况的原因是在主线程中创建了进度条。我们应该单独用一个线程来执行CalculateSomething函数,然后在每次迭代中给主线程发信号来逐步更新进度条。前面提到过,线程在CPU中以极快的速度切换,在我们看来进度条的更新与计算进度同步进行。

总而言之,每次处理并行任务时,如果要等待用户输入或依赖外部(如,远程服务器的响应),就应该为类似的操作单独创建一个线程,这样我们的程序才不会挂起无响应。
时间: 2024-07-30 18:31:53

《C++多线程编程实战》——1.3 程序结构、执行流和运行时对象的相关文章

《C++多线程编程实战》导读

前言 C++多线程编程实战多线程编程正逐渐成为IT行业和开发人员关注的焦点.开发商希望开发出用户友好.界面丰富,而且能并发执行的应用程序.强大的C++语言和本地Win32 API特性为多线程编程提供了良好开端.有了强大的C++,可以轻松地创建不同类型的应用程序,执行并行,而且还能优化现有的工作. 本书是一本实践为主.通俗易懂的Windows多线程编程指导.你将学到如何从多线程方案中受益,增强你的开发能力,构建更好的应用程序.本书不仅讲解了创建并行代码时遇到的问题,而且还帮助读者详细理解同步技术.

《C++多线程编程实战》——第1章 C++概念和特性简介1.1 介绍

第1章 C++概念和特性简介 C++多线程编程实战 本章介绍以下内容: 创建一个C++项目 程序结构.执行流.运行时对象 结构编程方法 理解面向对象编程方法 解释继承.重载和覆盖 理解多态 事件处理器和消息传递接口 链表.队列.栈示例 1.1 介绍 系统所执行的程序的进程或抽象是所有操作系统的核心概念.现在,绝大多数的操作系统在同一时间内都可以进行多项操作.例如,计算机在用户编辑Word文档时,还可以打印该文档.从硬盘缓冲区读数据.播放音乐等.在多任务操作系统中,中央处理单元(CPU)在程序中快

Java多线程编程实战之不提倡的方法

不提倡使用的方法是为支持向后兼容性而保留的那些方法,它们在以后的版本中可能出现,也可能不出现.Java 多线程支持在版本 1.1 和版本 1.2 中做了重大修订,stop().suspend() 和 resume() 函数已不提倡使用.这些函数在 JVM 中可能引入微妙的错误.虽然函数名可能听起来很诱人,但请抵制诱惑不要使用它们. 调试线程化的程序 在线程化的程序中,可能发生的某些常见而讨厌的情况是死锁.活锁.内存损坏和资源耗尽. 死锁 死锁可能是多线程程序最常见的问题.当一个线程需要一个资源而

《C++多线程编程实战》——第2章 进程和线程的概念2.1 简介

第2章 进程和线程的概念 C++多线程编程实战本章介绍以下内容: 进程和线程解释进程模型进程的实现进程间通信(IPC)解决典型的IPC问题线程模型的实现线程的用法在用户空间实现线程在内核实现线程 2.1 简介 现在的计算机能同时处理多件事,许多Windows用户还没有完全意识到这一点.我们举例说明一下.当启动PC系统时,许多进程都在后台启动(例如,管理电子邮件的进程.负责更新病毒库的进程等).通常,用户在执行其他任务时(如,上网),还会打印文件或播放CD.这些活动都需要管理.支持多进程的多任务系

《JAVA多线程编程实战指南》之Two-phase Termination(两阶段终止)模式

本文是<JAVA多线程编程实战指南>的样章,感谢作者授权并发网(ifeve.com)发表此文.感谢demochen整理此文. 5.1Two-phase Termination模式简介 停止线程是一个目标简单而实现却不那么简单的任务.首先,Java没有提供直接的API用于停止线程.此外,停止线程还有一些额外的细节需要考虑,如停止的线程处于阻塞(如等待锁)或者等待状态(等待其他线程),尚有未处理完的任务等. Two-phase Termination模式通过将停止线程这个动作分解为准备阶段和执行阶

精品赏析:一个.NET程序在编译和运行时都做了些什么?

编译|程序 一个.NET程序在编译和运行时都做了些什么?================================================================在新闻组和邮件列表里有大量关于一个.Net程序的设计编译(design-time orrun-time)和运行原理 (CPU-specific binary or pseudo-code)的疑问. 这里是一个简单的回答:当你编译一个C#应用程序或任何一种CLS(CommmonLanguage Specificati

《Java并发编程实战》学习笔记 线程安全、共享对象和组合对象

第一章 介绍 线程的优势: 充分利用多处理器 简化模型 简化异步事件的处理 提供用户界面的响应(时间) 线程的风险: 安全的风险(不好的事情会发生),提高错误出现的几率 活性的风险(好的事情不会发生),如某些代码不会执行,出现死锁.活锁以及饥饿 性能的风险,不好的多线程编程可能会危害性能 第二章 线程安全 编写线程安全的代码,实质是管理对状态的访问,尤其是那些共享.可变的状态.对象的状态包括任何能影响它外部可见行为的数据. 当有过个线程能访问状态变量时,而且他们当中能对变量进行修改,则需要对他们

Java多线程编程实战之基础

在 Java 程序中使用多线程要比在 C 或 C++ 中容易得多,这是因为 Java 编程语言提供了语言级的支持.本文通过简单的编程示例来说明 Java 程序中的多线程是多么直观.读完本文以后,用户应该能够编写简单的多线程程序. 为什么会排队等待? 下面的这个简单的 Java 程序完成四项不相关的任务.这样的程序有单个控制线程,控制在这四个任务之间线性地移动.此外,因为所需的资源 - 打印机.磁盘.数据库和显示屏 -- 由于硬件和软件的限制都有内在的潜伏时间,所以每项任务都包含明显的等待时间.因

Java多线程编程实战之限制优先级

限制线程优先级和调度 Java 线程模型涉及可以动态更改的线程优先级.本质上,线程的优先级是从 1 到 10 之间的一个数字,数字越大表明任务越紧急.JVM 标准首先调用优先级较高的线程,然后才调用优先级较低的线程.但是,该标准对具有相同优先级的线程的处理是随机的.如何处理这些线程取决于基层的操作系统策略.在某些情况下,优先级相同的线程分时运行:在另一些情况下,线程将一直运行到结束.请记住,Java 支持 10 个优先级,基层操作系统支持的优先级可能要少得多,这样会造成一些混乱.因此,只能将优先