1.1进程与线程的概念:
进程是指在系统中正在运行的一个应用程序,在传统的操作系统中,是资源的分配单位又是调度运行的单位。
线程是指进程中执行运行的最小单位,即处理机调度的基本单位。
进程是一项任务,线程是独立子任务,可由不同处理器分别来完成,提高了进程运行速度。
1.2进程与线程的比较:
一个程序最少有一个进程,一个进程至少有一个线程。
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的,每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
1.3为什么用线程而不用进程
数据表明,线程是更加经济的,启动快、退出快、对系统资源冲击少,在win32种,线程分享了大部分核心对象,如文件句柄的拥有权。
启动一个进程,必须为进程分配内存,初始化,有太多工作要做。
因为多线程可以独立运行,所以用多线程编程可以:
1)提高应用程序响应,利用多线程编程并不一定能加快程序运行的速度,其目的是拥有更加良好的程序响应。任何一个包含很多互不关联的操作的程序都可以被重新设计,使得每一个操作成为一个线程。例如,在一个GUI内执行一个操作的同时启动另外一个,则可以用多线程改善性能。
2)使多个CPU系统更加有效,典型情况下,有同时需求的多线程应用程序不需要考虑处理器的数量,应用程序的性能在被多处理器改善的同时对用户是透明。对于数学计算和有高度并发性需求的应用程序,如矩阵乘法,在多处理器平台上可以用多线程来提高速度。
3)改善程序结构。许多应用程序可以一个单一的、巨大的线程改造一些独立或半独立的执行部分,从而得到更有效的运行,多线程比但线程程序适应用户需求的变更
4)占用更少的系统资源。线程的数据结构简单,停止、运行速度快,进程是线程的靠山,是车间,线程是小组,活动方便,进程任务大,信息多,将它细分为线程后,各线程可共享进程分到的资源,调度方便。
5)改善性能
2.1引入同步机制的原因:
第一个原因:为了控制线程之间的资源同为多个线程在共享资源时如果繁盛访问冲突通常会带来不正确的后果。
第二个原因:有时要求确保线程之间的动作以指定的次序发生,如一个线程需要等待由另外一个线程需要等待由另外一个线程所引起的事件。
2.2 MSDN实例代码
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <conio.h> #include <time.h> #include <process.h> void Bounce(void *ch); void CheckKey(void *dummy); #define GetRandom(min,max) ((rand()%(int)(((max)+1)-(min))) + (min) )// GetRandom获得一个min或max之间的随机整数 BOOL repeat=TRUE; //重复标志,用作控制线程的退出 HANDLE hStdOut; //控制台窗口句柄 CONSOLE_SCREEN_BUFFER_INFO csbi; //描述控制台信息的结构 int main(int argc, char* argv[]) { CHAR ch='A'; hStdOut=GetStdHandle(STD_OUTPUT_HANDLE);//获取显示屏大小,如长宽 GetConsoleScreenBufferInfo(hStdOut,&csbi);//启动CheckKey线程来等待键盘输入,此线程用来控制线程和程序的终止 _beginthread(CheckKey,0,NULL); while(repeat) { _beginthread(Bounce,0,(void*)(ch++)); Sleep(1000L); } return 0; } //CheckKey这一线程等待键盘输入,然后清除repeat标志 void CheckKey(void *dummy) { _getch(); repeat=0; repeat=0; } //Bounce这一线程负责创建和控制在屏幕上四处移动的彩色字符 void Bounce(void *ch) { //根据线程参数产生颜色 char blanckcell = 0x20; char blockcell =(char)ch; BOOL first=TRUE; COORD oldcoord,newcoord; DWORD result; //根据当前时间产生随机数,以使每次产生的数字是不同的 srand((unsigned)time(NULL)); //获得初始位置 newcoord.X=GetRandom(0,csbi.dwSize.X-1); newcoord.Y=GetRandom(0,csbi.dwSize.Y-1); while(repeat) { //每次循环中暂停100ms Sleep(100L); //在屏幕上刷新老位置,在新位置绘制字符 if(first) first=FALSE; else WriteConsoleOutputCharacter(hStdOut,&blanckcell,1,oldcoord,&result); //进行位置转变 oldcoord.X=newcoord.X; oldcoord.Y=newcoord.Y; newcoord.X += GetRandom(-1,1); newcoord.Y += GetRandom(-1,1); //如果将要超出屏幕,那么对位置进行调整,还产生声音 if (newcoord.X < 0) { newcoord.X = 1; } else if(newcoord.X == csbi.dwSize.X) newcoord.X=csbi.dwSize.X-2; else if(newcoord.Y < 0) newcoord.Y =1; else if(newcoord.Y == csbi.dwSize.Y) newcoord.Y = csbi.dwSize.Y-2; else continue; Beep(((char)ch - 'A')*100,175); } _endthread(); }
如果用vc++6.0调试时如果遇到:
error C2065: '_beginthread' : undeclared identifier
error C2065: '_endthread' : undeclared identifier
需要:
工程”->“设置”—>“C/C++”
在“分类”里选择“Code Gerneration”
在“Use run-time library”里选择“Debug Multithreaded”