1 / 28

Chap11 多线程编程

Chap11 多线程编程. 本章大纲. 进程和线程基础知识 CWinThread 线程的创建和启动 线程的终止 线程间的通讯和同步 MTRECALC 例程序分析 MTGDI 例程序分析 MUTEXES 例程序分析. 进程和线程基础知识. 什么是进程 什么是线程 进程和线程的关系 进程和线程的优先级 辅助线程和用户界面线程. 进程是指在系统中正在运行的一个应用程序。. 什么是进程?. 进程用有它自己的内存、文件句柄及其他系统资源。. 进程具有自己私有的 4GB 虚拟地址空间。. 线程是操作系统分配处理时间的基本单元。它代表一个独立的执行路径。.

keefe
Download Presentation

Chap11 多线程编程

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chap11 多线程编程

  2. 本章大纲 • 进程和线程基础知识 • CWinThread • 线程的创建和启动 • 线程的终止 • 线程间的通讯和同步 • MTRECALC例程序分析 • MTGDI 例程序分析 • MUTEXES 例程序分析

  3. 进程和线程基础知识 • 什么是进程 • 什么是线程 • 进程和线程的关系 • 进程和线程的优先级 • 辅助线程和用户界面线程

  4. 进程是指在系统中正在运行的一个应用程序。 • 什么是进程? 进程用有它自己的内存、文件句柄及其他系统资源。 进程具有自己私有的4GB虚拟地址空间。

  5. 线程是操作系统分配处理时间的基本单元。它代表一个独立的执行路径。线程是操作系统分配处理时间的基本单元。它代表一个独立的执行路径。 • 什么是线程? 每个线程有自己的栈和一份CPU寄存器的拷贝。 • 进程和线程的关系? 一个进程至少包括一个主线程,可以有多个子线程。 每个进程的所有线程共享同一个地址空间。

  6. 高优先级线程优先运行,优先级相同的线程按照时间片轮流运行高优先级线程优先运行,优先级相同的线程按照时间片轮流运行 • 进程和线程的优先级 线程的调度优先级:0~31级 0~15 级是普通优先级 只有系统线程可以设置0优先级 16~31级是实时优先级 优先级相同的线程不是按照时间片轮流运行,而是先运行的线程控制CPU。

  7. 线程的调度优先级=进程类基本优先级+线程相对优先级线程的调度优先级=进程类基本优先级+线程相对优先级 HIGH_PRIORITY_CLASS IDLE_PRIORITY_CLASS NORMAL_PRIORITY_CLASS REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_IDLE THREAD_PRIORITY_LOWEST THREAD_PRIORITY_NORMAL THREAD_PRIORITY_TIME_CRITICAL

  8. (Worker Threads ) (User-Interface Threads ) • 辅助线程和用户界面线程 提供消息机制。 用来处理用户输入,响应事件和消息。 用来执行后台任务如:复杂计算、后台打印。 没有消息机制。

  9. CWinThread类 • 是所有线程类的基类。 • 派生类CWinApp用于创建主线程 • CWinThread类题供了辅助线程和用户界面线程的支持。 • 创建线程 • CWinThread::CreateThread • 启动线程:DWORD ResumeThread( ); • 挂起线程:SuspendThread( ); • 设置优先级:SetThreadPriority( int nPriority ); • 重载函数

  10. 可重载函数

  11. 线程的创建和启动 指向辅助线程的控制函数。 UINT MyControllingFunction( LPVOID pParam ) • 创建辅助线程 CWinThread*AfxBeginThread (AFX_THREADPROCpfnThreadProc, LPVOIDpParam, intnPriority=THREAD_PRIORITY_NORMAL, UINTnStackSize=0, DWORDdwCreateFlags=0, LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL); 传给控制函数的参数 • CREATE_SUSPENDED挂起线程 • 0  --启动线程

  12. 线程的创建和启动 • 创建用户界面线程 1.CWinThread*AfxBeginThread ( CRuntimeClass*pThreadClass, intnPriority=HREAD_PRIORITY_NORMAL, UINTnStackSize=0, DWORDdwCreateFlags= 0, LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL); 2. CWinThread::CreateThread

  13. 线程的终止 • Normal Thread Termination • 辅助线程: 退出控制函数,并返回整型值. 正常退出返回0。 • 用户界面线程: 在线程内调用 ::PostQuitMessage函数. • Premature Thread Termination 调用AfxEndThread 函数. • Retrieving the Exit Code of a Thread BOOL GetExitCodeThread ( HANDLE hThread, // handle to the thread LPDWORD lpExitCode // address to receive termination status ); • STILL_ACTIVE线程在活动状态 • exit code   --线程终止

  14. 线程间的通讯和同步 • 使用全局变量进行线程间通讯 • 把全局变量声明为Volatile,确保该变量不存储在寄存器中。 • 使用同步机制 • 同步对象:CSyncObject, CSemaphore, CMutex, CCriticalSection, 和 CEvent • 同步访问对象:CMultiLock和CSingleLock

  15. 事件和CEvent 允许一个线程通知另一个线程发生了某个事件 CEvent( BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL ) BOOL SetEvent( ) 设置有信号状态 BOOL ResetEvent( )设置无信号状态

  16. 事件同步 使用CEvent类创建全局事件对象,“启动”事件和“终止”事件。 主线程设定事件信号状态: • 调用CEnvent::SetEnvent函数设定事件为有信号状态。 辅助线程监视事件 • 使用CSingleLock类 • 使用Win32 WaitForSingleObject函数

  17. DWORD WaitForSingleObject ( HANDLE hHandle, // handle to object to wait for DWORD dwMilliseconds // time-out interval in milliseconds ); • INFINITE- 直到hHandle对象成为有信号状态才返回 。 • 0-立即返回。 返回值: WAIT_ABANDONED:互斥信号量处于无信号状态。 WAIT_OBJECT_0 : hHandle对象处在有信号状态。 WAIT_TIMEOUT :等待时间超时,hHandle对象处在无信号状态。

  18. 临界区和CCriticalSection • 临界区只供单个进程的线程使用,可保证在任何时候只有一个线程访问某项资源。 • CCriticalSection封装了临界区对象 • CCriticalSection(); • virtual BOOL Unlock( ); • BOOL Lock( );

  19. 互斥量和CMutex类 • 与临界区的作用相似,允许在任意时刻有且仅有一个线程访问某资源。 • 有应用程序需要用同一个资源时,使用互斥量。只有一个进程需要用一个资源时,使用临界区。 • CMutex(BOOLbInitiallyOwn = FALSE,LPCTSTR lpszName = NULL,LPSECURITY_ATTRIBUTESlpsaAttribute = NULL);

  20. 信号量和CSemaphore类 • 信号量对象允许有限数量的线程存取某个共享的资源,采用计数器来实现信号量。 • CSemaphore类对象代表一个信号量对象。它维护着在访问指定资源的线程个数。 • CSemaphore( LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName = NULL, LPSECURITY_ATTRIBUTES lpsaAttributes = NULL );

  21. 访问同步对象 • 信号量、事件、互斥量等同步对象的访问和控制需要通过CSingleLock或CMultiLock对象来实现。 • 当在某一时刻只需要访问一个同步对象时,使用CSingleLock类。 • CSingleLock( CSyncObject* pObject, BOOL bInitialLock = FALSE ); • 当在某一时刻需要访问多个同步对象时,使用CMultiLock类。 • CMultiLock( CSyncObject* ppObjects[ ], DWORD dwCount, BOOL bInitialLock = FALSE );

  22. CSingleLock和CMultiLock的成员函数 • IsLocked判断同步对象是否被锁定 • Lock 等待一个同步对象 • Unlock 释放一个同步对象

  23. MUTEXES 例程序分析 CMutex m_mutex; //创建对象 int CDisplayThread::Run() { …. CSingleLock sLock(&(m_pOwner->m_mutex)); sLock.Lock(); // Construct a string with the string form of the number. strBuffer = _T("Dspy: "); strBuffer += m_pOwner->m_strNumber; sLock.Unlock(); … }

  24. MUTEXES 例程序分析 int CCounterThread::Run() { CSingleLock sLock(&(m_pOwner->m_mutex)); sLock.Lock(); _stscanf((LPCTSTR) m_pOwner->m_strNumber, _T("%d"), &nNumber); nNumber++; m_pOwner->m_strNumber.Empty();

  25. while (nNumber != 0) { m_pOwner->m_strNumber += (TCHAR) ('0' + nNumber%10); // A call to Sleep() here tells the system that we want // to relinquis the remainder of our time slice to // another thread. Sleep(0); // get ready to get the next digit. nNumber /= 10; } // Characters were generated in reverse order, // reverse the string m_pOwner->m_strNumber.MakeReverse(); sLock.Unlock(); …. }

More Related