多任务编程05.ppt
文本预览下载声明
线程同步和互斥 第五章 线程同步和互斥 线程同步 线程需要在两种情况下互相进行同步 ??有多个线程访问共享资源而不使资源被破坏时 ??当一个线程需要将某个任务以完成的情况通知另外一个或多个线程时 ??Windows线程通常使用的同步和互斥手段关键代码段(CriticalSection),互斥量(Mutex),信号量(Semaphore),事件(Event) 用户方式的线程同步 ??用户方式的线程同步包括互锁函数和关键代码段 用户方式顾名思义是指工作在用户态而不是核心态的。 ??原子访问:互锁的函数家族。 例:InterlockedIncrement ??关键代码段(临界区) 所谓原子访问,是指线程在访问资源的时候能够确保所有的线程都不在同一时间访问相同的资源 互锁的函数家族 函数参数和功能InterlockedIncrement参数为PLONG类型。此函数使一个LONG变量增1InterlockedDecrement参数为PLONG类型。此函数使一个LONG变量减1InterlockedExchangeAdd参数1为PLONG类型,参数2为LONG类型。此函数将参数2赋给参数1指向的值InterlockedExchange参数1为PLONG类型,参数2为LONG类型。此函数将参数2的值赋给参数1指向的值InterlockedExchangePointer参数为PVOID* 类型,参数2为PVOID类型。此函数功能同上。具体参见帮助InterlockedCompareExchange参数1为PLONG类型,参数2为LONG类型,参数3为LONG类型。此函数将参数1指向的值与参数3比较,相同则把参数2的值赋给参数1指向的值。不相同则不变InterlockedCompareExchangePointer参数1为PVOID* 类型,参数2为PVOID类型,参数3为PVOID。此函数功能同上。具体参见帮助 关键代码段(临界区) ??关键代码段是指一个小的代码段,在代码能够执行前,它必须独占对某些共享资源的访问权。当然,系统能够抑制你的线程进行运行,但是,在线程退出关键代码段之前,系统不给想要访问相同资源的其他任何线程进行调度 EnterCriticalPolicySection进入关键代码段 void EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection); LeaveCriticalPolicySection离开关键代码段 void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection); 使用这两个函数来标志一段关键代码段 关键代码段例子 LPCRITICAL_SECTION g_cs; longg_alDataList 在Thread1中操作 { EnterCriticalSection(g_cs);// 进入关键代码段 ….. // 读取或者写入数组g_alDataList …. LevelCriticalSection(g_cs); } 在Thread2中也需要有同样的形式来标志关键代码段. 使用关键代码段 ??注意:必须所有访问这个共享资源的线程都使用相同的规则,即都使用关键代码段进行保护,才能达到效果。如果Thread1使用了关键代码段进行了保护,但是Thread2没有使用关键代码段进行保护,直接访问了g_alDataList, 也不能达到保护的目的 ??每个共享资源使用一个LPCRITICAL_SECTION变量。比如有两个共享资源a,b, Thread1只需要访问a就可以,Thread2 和Thread3 需要访问a, b, 则a和b使用不同的LPCRITICAL_SECTION变量 ??同时访问多个共享资源,不同的线程按照相同的顺序进入和离开关键代码段 ??不要长时间运行关键代码段,否则其他线程进入等待状态。会降低应用程序的性能 使用互锁函数和关键代码段的缺点 ??互锁函数只能对单值变量进行操作,不能对结构体等其他复杂结构进行操作 ??关键代码段只能在同一个进程之中的线程间保持同步 ??Critical Section不是一个核心对象,无法获知进入临界区的线程是生是死 ??不要长时间锁住一份资源。这里的长时间是相对的,视不同程序而定。对一些控制软件来说,可能是数毫秒,但是对另外一些程序来说,可以长达数分钟。但进入临界区后必须尽快地离开,释放资源 ??使用内核对象进行同步的机制的适应性远远优于用户方式的线程同步 使用内核对象进行同步控制 ??Win32的各种内核对象如Mutex,Semaphore,Event等,这些内核对象
显示全部