Windows线程创建

合集下载

MFC中的多线程问题

MFC中的多线程问题

3 多线程的调度和处理在32 位Windows 环境下,开发多线程应用程序可以利用提供的Win32 API 接口函数,也可以利用VC++ 中提供的MFC类库进行开发。

两种方式对于多线程编程原理是一样的,用户可以根据需要选择相应的工具。

下面以利用MFC 类库实现多线程调度与处理为例,介绍多线程的实现方法以及多个线程间任务调度所应注意的一些关键技术。

3.1 基于MFC的多线程设计在VC++6.0环境下,MFC类库提供了对多线程编程支持,使得多线程能方便的实现。

MFC区分两种类型的线程:辅助线程(Worker Thread)和用户界面线程(UserInterface Thread)。

辅助线程没有消息机制,通常用来执行后台计算和维护任务。

MFC 为用户界面线程提供消息机制,用来处理用户的输入,响应用户产生的事件和消息。

但对于Win32 的API 来说,这两种线程并没有区别,它只需要线程的启动地址以便启动线程执行任务。

用户界面线程的一个典型应用就是类CWinApp,类CwinApp是CWinThread 类的派生类,应用程序的主线程是由它提供,并由它负责处理用户产生的事件和消息。

类CwinThread 是用户接口线程的基本类。

CWinThread 的对象用以维护特定线程的局部数据。

因为处理线程局部数据依赖于类CWinThread,所以所有使用MFC 的线程都必须由MFC 来创建。

3.2 多线程的创建及涉及的关键问题要创建一个线程,需要调用函数AfxBeginThread。

该函数通过参数重载可以实现辅助线程和用户界面线程的创建。

但不论是辅助线程还是用户界面线程,都需要指定额外的参数以修改优先级,堆栈大小,创建标志和安全特性等。

函数AfxBeginThread 返回指向CWinThread 类对象的指针。

创建助手线程相对简单,并不必须从CWinThread 派生一个类。

实现起来需要两步:实现控制函数和启动线程。

[NI技术] LabWindowCVI中的多线程技术

[NI技术] LabWindowCVI中的多线程技术

[NI技术] LabWindows™/CVI中的多线程技术多任务、多线程和多处理这些术语经常被交替地使用,但是它们在本质上是不同的概念。

多任务是指操作系统具有在任务间快速切换使得这些任务看起来是在同步执行的能力。

在一个抢占式多任务系统中,应用程序可以随时被暂停。

使用多线程技术,应用程序可以把它的任务分配到单独的线程中执行。

在多线程程序中,操作系统让一个线程的代码执行一段时间(被称为时间片)后,会切换到另外的线程继续运行。

暂停某个线程的运行而开始执行另一个线程的行为被称为线程切换。

通常情况下,操作系统进行线程切换的速度非常快,令用户觉得有多个线程在同时运行一样。

多处理指的是在一台计算机上使用多个处理器。

在对称式多处理(SMP)系统中,操作系统自动使用计算机上所有的处理器来执行所有准备运行的线程。

借助于多处理的能力,多线程应用程序可以同时执行多个线程,在更短的时间内完成更多的任务。

单线程应用程序移植到多核处理器上运行不会获得性能上的改进,这是因为它们只能在其中一个处理器上运行,而不能像多线程应用程序那样在所有的处理器上同时运行。

而且单线程应用程序需要承受操作系统在处理器间切换所需要的开销。

为了在多线程操作系统和/或多处理器计算机上获得最优异的性能,我们必须使用多线程技术来编写应用程序。

目录1. 进行多线程编程的原因2. 选择合适的操作系统3. LabWindows/CVI中的多线程技术简介4. 在LabWindows/CVI的辅助线程中运行代码5. 保护数据6. 避免死锁7. 监视和控制辅助线程8. 进程和线程优先级9. 消息处理10. 使用线程局部变量11. 在线程局部变量中存储动态分配的数据12. 在独立线程中运行的回调函数13. 为线程设定首选的处理器1. 进行多线程编程的原因在程序中使用多线程技术的原因主要有四个。

最常见的原因是多个任务进行分割,这些任务中的一个或多个是对时间要求严格的而且易被其他任务的运行所干涉。

windows后门程序的心得与小技巧

windows后门程序的心得与小技巧

windows后门程序目录一.具体实现(已完成)1.对话匡界面弹框按钮 (2)2.窗口间消息 (2)3.编辑框:没有id? (2)4.窗口重绘必须立即完成: (2)5.创建线程(beginthreadex为何未定义?) (2)6.c/s聊天 (3)7.获取本机ip (7)8.向本机自动更新(留后门) (8)9.域名转换函数...............................................................、 (12)10.去除http协议响应头 (12)二.未完成 (13)三.心得体会 (14)●套接字收发整形数据C库函数与windows函数,●.代码量与可移植性●套接字接收缓冲区应该大一些?●.套接字接收绑定●自动补充路径●域名转换ip一.已完成1.对话匡界面弹框按钮hbut2=CreateWindow(TEXT("edit"),NULL,WS_CHILD|WS_VISIBLE|WS_BORDER|BS_TEXT,10,30,100,25,hwnd,(HMENU) 3,hinst,NULL);hbut3=CreateWindow(("button"),("发送"),WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,300,300,100,30,hwnd,(HMENU)2,hinst,NULL);2.窗口间消息SendMessage(hwnd,WM_PAINT,wparam,lparam);3.编辑框:没有id?GetWindowText(hbut2,str_buf,10);得到文本//GetDlgItemText(hbut2,3,str_buf,10);得到空?4.窗口重绘必须立即完成:UpdateWindow(hwnd);InvalidateRect(hwnd,NULL,TRUE);5.创建线程(beginthreadex为何未定义?)int WINAPI threadproc(sock_block* dwtherdparam){return 0;}HANDLE initthread(sock_block* dwtherdparam){DWORD threadid;//_beginthreadex???????未定义?????dwtherdparam->dwrd=NULL;dwtherdparam->addr="192.168.127.0";dwtherdparam->honst=NULL;HANDLE h_thread=(HANDLE)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadproc,(void*)dwtherdparam,0,&threadid);return h_thread;}6.c/s聊天通过将目标机设置能服务器,本地机设置成客户端来实现,具体是目标创建线程,来开放端口监听套接字,(将目标设置成服务器是因为服务器可以长时间运行能够满足客户端随机登陆的要求并且性能消耗不大)。

Windows下多线程同步机制

Windows下多线程同步机制

多线程同步机制Critical section(临界区)用来实现“排他性占有”。

适用范围是单一进程的各线程之间。

它是:·一个局部性对象,不是一个核心对象。

·快速而有效率。

·不能够同时有一个以上的critical section被等待。

·无法侦测是否已被某个线程放弃。

MutexMutex是一个核心对象,可以在不同的线程之间实现“排他性占有”,甚至几十那些现成分属不同进程。

它是:·一个核心对象。

·如果拥有mutex的那个线程结束,则会产生一个“abandoned”错误信息。

·可以使用Wait…()等待一个mutex。

·可以具名,因此可以被其他进程开启。

·只能被拥有它的那个线程释放(released)。

SemaphoreSemaphore被用来追踪有限的资源。

它是:·一个核心对象。

·没有拥有者。

·可以具名,因此可以被其他进程开启。

·可以被任何一个线程释放(released)。

Ev ent ObjectEv ent object通常使用于overlapped I/O,或用来设计某些自定义的同步对象。

它是:·一个核心对象。

·完全在程序掌控之下。

·适用于设计新的同步对象。

· “要求苏醒”的请求并不会被储存起来,可能会遗失掉。

·可以具名,因此可以被其他进程开启。

Interlocked Variable如果Interlocked…()函数被使用于所谓的spin-lock,那么他们只是一种同步机制。

所谓spin-lock是一种busy loop,被预期在极短时间内执行,所以有最小的额外负担(overhead)。

系统核心偶尔会使用他们。

除此之外,interlocked variables主要用于引用技术。

他们:·允许对4字节的数值有些基本的同步操作,不需动用到critical section或mutex之类。

操作系统实验二并发与调度

操作系统实验二并发与调度

实验二并发与调度一、实验目的在本实验中,通过对事件和互斥体对象的了解,来加深对Windows 2000线程同步的理解。

通过分析实验程序,了解管理事件对象的API。

了解在进程中如何使用事件对象,在进程中如何使用互斥体对象,线程如何通过文件映射对象发送数据。

二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Windows 2000 Professional,Visual C++ 6.0专业版或企业版。

三、实验内容和步骤第一部分:互斥体对象本程序中显示的类CCountUpDown使用了一个互斥体来保证对两个线程间单一数值的访问。

每个线程都企图获得控制权来改变该数值,然后将该数值写入输出流中。

创建者实际上创建的是互斥体对象,计数方法执行等待并释放,为的是共同使用互斥体所需的资源(因而也就是共享资源) 。

1、利用互斥体保护共享资源程序参见实验指导书分析程序的运行结果,可以看到线程(加和减线程) 的交替执行(因为Sleep() API允许Windows切换线程) 。

在每次运行之后,数值应该返回初始值(0) ,因为在每次运行之后写入线程在等待队列中变成最后一个,内核保证它在其他线程工作时不会再运行。

1)请描述运行结果(如果运行不成功,则可能的原因是什么?) :2) 根据运行输出结果,对照分析程序,可以看出程序运行的流程吗?请简单描述:_____逆向运行__________第二部分线程通过文件对象发送数据Windows 2000提供的线程间通讯类内核对象允许同一进程或跨进程的线程之间互相发送信息,包括文件、文件映射、邮件位和命名管道等,其中最常用的是文件和文件映射。

这类对象允许一个线程很容易地向同一进程或其他进程中的另一线程发送信息。

1、演示线程通过文件对象发送数据程序参见实验指导书运行结果(如果运行不成功,则可能的原因是什么?) :阅读和分析程序,请回答问题:1) 程序中启动了多少个单独的读写线程?__________100__________________________________________________________2) 使用了哪个系统API函数来创建线程例程?_________ CreateThread()________________________________3) 文件的读和写操作分别使用了哪个API函数?_______ ReadFile()______ WriteFile()_____________ 每次运行进程时,都可看到程序中的每个线程从前面的线程中读取数据并将数据增加,文件中的数值连续增加。

mt02Windows内核对象

mt02Windows内核对象

Windows编程-多任务编程 编程- 编程
2.16
X.J.Lee ©2008
2.5 等待内核对象
等待单个内核对象--WaitForSingleObject 等待单个内核对象--WaitForSingleObject --
函数原型 WaitForSingleObject( HANDLE hHandle, // 内核对象句柄 DWORD dwMilliseconds //等待时间 ) WaitForSingleOjbect函数可以等待一个内核对象,直到该内核 对象的状态变为已通知状态,或者指定的等待时间已经到了, 否 则等待的线程处于等待态,是不占用CPU的,当等待的时间到了 ,函数返回WAIT_TIMEOUT ,如果是等待的对象变成已通知, 则返回WAIT_OBJECT_0 。
Windows编程-多任务编程 编程- 编程 2.11 X.J.Lee ©2008
HANDLE hThreadHandle = CreateThread(NULL, 0, TaskMain,(LPVOID)this, 0, &dwThreadID);
判断这个线程是否创建成功,通常判断的方式是 判断这个线程是否创建成功, if (NULL == hThreadHandle ) { // 创建失败,处理错误。 。。。。 } 完全的判断方式是 if (NULL == hThreadHandle || INVALID_HANDLE_AVLUE == hThreadHandle) { // 创建失败,处理错误。 。。。。 }
Windows编程-多任务编程 编程- 编程
2.5
X.J.Lee ©2008
2.2 创建Windows内核对象 创建Windows内核对象
使用Windows内核函数来创建和操作内核对象。 内核函数来创建和操作内核对象 使用

Windows 95

Windows 95Windows 95Windows 95是美国微软公司1995年推出的操作系统。

Windows 95是一个混合的16位/32位Windows系统,其版本号为4.0,开发代号为Chicago。

由微软公司于1995年8月24日发行。

Windows 95是第一次抛弃了对前一代16位x86的支持,因此它要求英特尔公司的80386处理器或者在保护模式下运行于一个兼容的速度更快的处理器。

同时也是第一个特别捆绑了一个版本的DOS的视窗版本(Microsoft DOS 7.0)。

它带来了更强大的、更稳定、更实用的桌面图形用户界面,同时也结束了桌面操作系统间的竞争。

在它发行的一两年内,它成为有史以来最成功的操作系统之一。

简介Windows 95是一个混合的16位/32位Windows系统。

Windows 95 是微软之前独立的操作系统MS-DOS和视窗产品的直接后续版本。

第一次抛弃了对前一代16位x86的支持,因此它要求的80386处理器或者在保护模式下运行于一个兼容的速度更快的处理器。

它以对GUI的重Windows 95要的改进和底层工作为特征。

同时也是第一个特别捆绑了一个版本的DOS 的视窗版本(Microsoft DOS 7.0)。

这样,微软就可以保持由视窗3.x 创建起来的GUI市场的统治地位,同时使得没有非微软的产品可以提供对系统的底层操作服务。

也就是说,视窗95具有双重的角色。

它带来了更强大的、更稳定、更实用的桌面图形用户界面,同时也结束了桌面操作系统间的竞争。

(技术上说,Windows图形用户界面可以在DR-DOS上运行,也可能可以在PC-DOS上运行——这个情况直到几年后在法庭上被揭示,这时其它一些主要的DOS市场的商家已经退出市场了。

)编辑本段发布微软对Windows 95中文版精雕细刻、力求完美。

据统计,微软Windows 95在开发Windows 95中文版过程中总共投入了近10万人/小时;共派发了6000多套测试版本供用户测试及征求建议。

四种方式创建c++线程

四种⽅式创建c++线程线程和进程概念关系:进程是⼀组离散的(执⾏)程序任务集合;线程是进程上下⽂中执⾏的代码序列;两者之间具体关系:线程是进程的可执⾏单元,是计算机分配CPU机时的基本单元。

⼀个进程可以包含⼀个或多个线程,进程是通过线程去执⾏代码的。

同⼀个进程的多个线程共享该进程的资源和操作系统分配给该进程的内存空间。

每个进程必须有⼀个主线程,主线程退出之后该进程也就退出了。

⼀个进程的主线程是由系统创建的。

在单CPU中,表⾯上看好像是多个进程中的多个线程共同执⾏,实际上是操作系统根据调度规则、依次的将⼀个⼀个的线程可执⾏代码加载进CPU中执⾏的;即,CPU在同⼀时刻只能执⾏⼀段代码,由于CPU的频率⾮常快,迅速的在各个线程间进⾏切换,所以给⼈的感觉就好像是多个线程共同执⾏。

在多核CPU的电脑中,确实是多个线程共同执⾏,因为多核处理器中,每个核拥有⾃⼰的缓存、寄存器和运算器。

C++创建新线程的四种⽅式:⽅式⼀(不推荐):CreateThread(记得关闭线程句柄)CreateThread是⼀种微软在Windows API中提供了建⽴新的线程的函数,该函数在的基础上创建⼀个新线程。

终⽌运⾏后,线程对象仍然在系统中,必须通过CloseHandle函数来关闭该线程对象。

HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性,在Windows NT中,NULL使⽤默认安全性,不可以被⼦线程继承,否则需要定义⼀个结构体将它的bInheritHandle成员初始化为TRUE。

因此⼀般使⽤NULL SIZE_T dwStackSize, // 线程堆栈⼤⼩设置初始栈的⼤⼩,以字节为单位,如果为0,那么默认将使⽤与调⽤该函数的线程相同的栈空间⼤⼩。

任何情况下,Windows根据需要动态延长堆栈的⼤⼩LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数地址指向线程函数的指针,形式:@函数名,函数名称没有限制,LPVOID lpParameter, // 线程函数参数是⼀个指向结构的指针,不需传递参数时,为NULLDWORD dwCreationFlags, // 指定线程是否⽴即启动⼀般取值为0(⽴即激活)或者为)CREATE_SUSPENDED(0x00000004)挂起线程LPDWORD lpThreadId // 存储线程ID号);返回值:函数成功,返回线程句柄;函数失败返回false。

delphi多线程编程

◆delphi多线程编程之一create和Free◆(调试环境:Delphi2007+WinXPsp3 例程Tst_Thread.dpr)Google搜到线程的例子都是那个画图的,猛禽那个多线程又太过高深(对于我这一滴水来说),万一老师开线程的博还是要等。

只有自己看着《Delphi5开发人员指南》中文版PDF一步一步来弄懂些初步的东西,到时候可以跟上万一老师的课程。

一、创建:1、直接书写:unit Unit1;interfaceuses Classes;TMyThead = class(TThread)private{ Private declarations }protectedprocedure Execute; override;end;implementation{用鼠标放在上面的TMyThead上按ctrl+alt+c直接自动生成下面的}procedure TMyThead.Execute;begininherited;end;2、在File菜单的New—Others—Delphi Files里面选Thread Object,出来一个对话框,你在Thread名字里填TMyThread后,就会自动生成一个新的Unit2,里面的内容和上面一样。

二、简单例子:(例程:Tst_Thread.dpr)在一个Form上放3个按钮和一个Memo,然后加上下面这段。

TMyThead = class(TThread)private{ Private declarations }protectedprocedure Execute; override;end;varForm1: TForm1;m:integer;implementation{$R *.dfm}{ TMyThead }function Func1(const n:Integer):Integer; // 定义一个耗时函数来运行beginResult:=Round(abs(Sin(Sqrt(n))));end;procedure TMyThead.Execute;vari:integer;beginfor i := 0 to 20000000 doinc(m,Func1(i)); //m全局变量end;procedure TForm1.Button1Click(Sender: TObject);vari:integer;beginfor i := 0 to 20000000 doinc(m,Func1(i)); //m全局变量end;procedure TForm1.Button2Click(Sender: TObject);varMyThread:TMyThead;beginMyThread:=TMyThead.Create(False);end;procedure TForm1.Button3Click(Sender: TObject);beginMemo1.Lines.Add('ok'+inttostr(m));end;end.Button1Click后,Button3要过好几秒才能按下(嘿嘿,我的机子好,书上的例子i才200万,我加到20 00万Button3才延迟几秒)。

windows体系及编程实验指导书

《Windows体系及编程》实验指导书实验一进程管理实验实验名称:进程管理实验实验类型: 验证性实验学时: 4适用对象: 软件工程专业、网络工程专业、信息安全专业一、实验目的理解Windows编程环境下的进程管理机制,能创建一个完成特定功能的进程,并能对进程进行信息的获取、终止和保护。

二、实验要求1.编写一段程序,能够完成创建进程的功能,要求启动windows记事本程序(notepad.exe),同时打开一个文本文件,路径为:c:\system\user.log 。

并打印出新建进程ID。

2.获取当前系统进程信息,打印输出进程名称和ID号。

3.终止新创建的进程并获取退出代码。

三、实验原理(1)进程的创建进程的创建通过CreateProcess()函数来实现,CreateProcess()通过创建一个新的进程及在其地址空间内运行的主线程来启动并运行一个新的程序。

具体地,在执行CreateProcess()函数时,首先由操作系统负责创建一个进程内核对象,初始化计数为1,并立即为新进程创建一块虚拟地址空间。

随后将可执行文件或其他任何必要的动态链接库文件的代码和数据装载到该地址空间中。

在创建主线程时,也是首先由系统负责创建一个线程内核对象,并初始化为1。

最后启动主线程并执行进程的入口函数WinMain(),完成对进程和执行线程的创建。

CreateProcess()函数的原型声明如下:BOOL CreateProcess(LPCTSTR lpApplicationName, // 可执行模块名LPTSTR lpCommandLine, // 命令行字符串LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程的安全属性LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性BOOL bInheritHandles, // 句柄继承标志DWORD dwCreationFlags, // 创建标志LPVOID lpEnvironment, // 指向新的环境块的指针LPCTSTR lpCurrentDirectory, // 指向当前目录名的指针LPSTARTUPINFO lpStartupInfo, // 指向启动信息结构的指针LPPROCESS_INFORMATION lpProcessInformation // 指向进程信息结构的指针);(2)进程的获取进程的定义是为执行程序指令的线程而保留的一系列资源的集合。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

CreateThread 用法詳解 今天我給大家講一講 C++中的多執行緒程式設計技術,C++本身並沒有提供任何多執行緒機制,但是 在 windows 下,我們可以調用 SDK win32 api 來編寫多執行緒的程式,下面我就此簡單的講一 下: 創建執行緒的函數

HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD SIZE_T dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId //thread identifier );

在這裡我們只用到了第三個和第四個參數, 第三個參數傳遞了一個函數的位址, 也是我們要 指定的新的執行緒。 第四個參數是傳給新執行緒的參數指針 eg1: #include #include using namespace std; DWORD WINAPI Fun(LPVOID lpParamter) { while(1) { cout<<"Fun display!"<} } int main() { HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); CloseHandle(hThread); while(1) { cout<<"main display!"<} return 0; } 我們可以看到主執行緒(main 函數)和我們自己的執行緒(Fun 函數)是隨機地交替執行的, 但是兩個執行緒輸出太快,使我們很難看清楚,我們可以使用函數 VOID Sleep( DWORD dwMilliseconds // sleep time ); 來暫停執行緒的執行,dwMilliseconds 表示千分之一秒,所以 Sleep(1000); 表示暫停 1 秒 eg2: #include #include using namespace std; DWORD WINAPI Fun(LPVOID lpParamter) { while(1) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN ); //設置顏色為綠色,高亮 cout<<"Fun display!"

int main() { HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); CloseHandle(hThread); while(1) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE| FOREGROUND_INTENSITY ); //顏色為默認的白色(加亮) cout<<"main display!"

執行上述代碼,這次我們可以清楚地看到在螢幕上交錯地輸出 Fun display!和 main display!,我們發現這兩個函數確實是併發運行的,細心的讀者可能會發現我們的程式是每 當 Fun 函數和 main 函數輸出內容後就會輸出換行,但是我們看到的確是有的時候程式輸出 換行了,有的時候確沒有輸出換行,甚至有的時候是輸出兩個換行。這是怎麼回事? 下面我 們把程式改一下看看: eg3: #include #include using namespace std; DWORD WINAPI Fun(LPVOID lpParamter) { while(1) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN ); //設置顏色為綠色,高亮 cout<<"Fun display!"/*

int main() { HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); CloseHandle(hThread); while(1) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE| FOREGROUND_INTENSITY ); //顏色為默認的白色(加亮) cout<<"main display!"/*

我們再次運行這個程式, 我們發現這時候正如我們預期的, 正確地輸出了我們想要輸出的 內容並且格式也是正確的。 下面我就來講一下此前我們的程式為什麼沒有正確的運行。 多執行緒的程式時併發地運行的, 多個執行緒之間如果公用了一些資源的話, 我們並不能保證些資 源都能正確地被利用,因為這個時候資源並不是獨佔的,舉個例子吧: eg4: 假如有一個資源 int a = 3 有一個執行緒函數 selfAdd() 該函數是使 a = a+a 又有一個執行緒函數 selfSub() 該函數是使 a = a-a 我們假設上面兩個執行緒正在併發執行, 如果 selfAdd 在執行的時候,我們的目的是想讓 a 變成 6,但此時 selfSub 得到了運行的機會,所以 a 變成了 0,等到 selfAdd 的到執行的機會 後,a = a+a ,但是此時 a 確是 0,並沒有如我們所預期的那樣的到 6,我們回到前面 eg2, 在這裡,我們可以把螢幕看成是一個資源,這個資源被兩個執行緒所共用,加入當 Fun 函數 輸出了 Fun display!後,將要輸出 endl(也就是清空緩衝區並換行,在這裡我們可以不用理 解什麼事緩衝區),但此時 main 函數確得到了運行的機會,此時 Fun 函數還沒有來得及輸出換行就把 CPU 讓給了 main 函數,而這時 main 函數就直接在 Fun display!後輸出 main display!,至於為什麼有的時候程式會連續輸出兩個換行,讀者可以採用同樣的分析方法來分析,在這裡我就不多講了,留給讀者自己思考了。 那麼為什麼我們把 eg2 改成 eg3 就可以正確的運行呢?原因在於, 多個執行緒雖然是併發運行 的,但是有一些操作是必須一氣呵成的,不允許打斷的,所以我們看到 eg2 和 eg3 的運行結果是不一樣的。 那麼,是不是 eg2 的代碼我們就不可以讓它正確的運行呢? 答案當然是否,下面我就來講 一下怎樣才能讓 eg2 的代碼可以正確運行。 這涉及到多執行緒的同步問題。 對於一個資源被多個執行緒共用會導致程式的混亂,我們的解決方法是只允許一個執行緒擁有對共用資源的獨佔,這樣就能夠解決上面的問題了。

HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD BOOL bInitialOwner, // initial owner LPCTSTR lpName // object name ); 該函數用於創造一個獨佔資源,第一個參數我們沒有使用,可以設為 NULL,第二個參數指 定該資源初始是否歸屬創建它的進程,第三個參數指定資源的名稱。

HANDLE hMutex = CreateMutex(NULL,TRUE,"screen"); 這條語句創造了一個名為 screen 並且歸屬於創建它的進程的資源

BOOL ReleaseMutex( HANDLE hMutex // handle to mutex );

該函數用於釋放一個獨佔資源,進程一旦釋放該資源,該資源就不再屬於它了,如果還要用 到,需要重新申請得到該資源。申請資源的函數如下:

DWORD WaitForSingleObject( HANDLE hHandle, // handle to object DWORD dwMilliseconds // time-out interval );

第一個參數指定所申請的資源的控制碼,第二個參數一般指定為 INFINITE,表示如果沒有申 請到資源就一直等待該資源,如果指定為 0,表示一旦得不到資源就返回,也可以具體地指 定等待多久才返回,單位是千分之一秒。好了,該到我們來解決 eg2 的問題的時候了,我們 可以把 eg2 做一些修改,如下 eg5: #include #include using namespace std; HANDLE hMutex;

DWORD WINAPI Fun(LPVOID lpParamter) { while(1) { WaitForSingleObject(hMutex, INFINITE); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN ); //設置顏色為綠色,高亮

相关文档
最新文档