用户模式下线程同步.docVIP

  • 3
  • 0
  • 约6.8千字
  • 约 8页
  • 2017-11-16 发布于江苏
  • 举报
用户模式下线程同步

学习笔记:用户模式下的线程同步 windhawk 2012-3-29 概述 从最初的写并发服务器程序接触多线程的概念,到如今写一个远程注入程序,越来越多的和线程打起交道。我们通常熟悉也容易理解进程,而线程则作为对于一个具体执行流程的抽象出现。在同样一个程序“容器”中,可以同时存在多个执行流程,这些流程的状态完全由他们各自的Context决定的。一般的小程序只需要一个主线程就足够了,但是很多时候我们会需要多线程的协作处理。 其实,如果所有的线程都能够独自运行而不需要相互通信,Microsoft Windows将进入最佳运行状态。然而,同时存在的多个线程经常会发生各种各样的联系,需要进行“同步”才可以合作运行。一般来说有两种情况: 1. 需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 2. 一个线程需要通知其他线程某项任务已经完成 《Windows核心编程》从用户模式和内核模式两个层面来讨论线程的同步问题,由于是第一遍学习,理解的程度有限,所以没有涉及条件变量部分,只就自己感觉学有所获的几个知识点做一个小结。这篇笔记的结构如下:  原子访问:Interlocked系列函数  关键段  Slim读写锁 原子访问 线程同步的一大部分与原子访问(atomic access)有关。所谓原子访问,就是一个线程在访问某个资源的同时能够保证没有其他线程会在同一时刻访问同一资源。Windows是一个多线程抢占式系统,这也就意味着系统可以随时挂起一个线程而去执行另一个线程,这中间由于CPU和线程本身的关系就会出现各种各样的同步逻辑错误,比如下面我们要举的例子。原子访问的“原子性”就在于一个原子访问是不能被中途打断的,只有在一个原子访问结束之后才可以接受另一个线程的访问。Windows为我们提供了Interlocked系列函数来实现这一功能。 LONG InterlockedExchangeAdd( PLONG volatile plAddend, //要计算的长整型变量的地址 LONG lIncrement //指定的长整型增量 ); 这个函数对传入的变量(*plAddend)增加lIncrement的值,可正可负。volatile要求系统不要进行代码优化,每次CPU都从内存读取值,而不是优化偷懒从寄存器中读取。当然我们还有类似于赋值的函数: LONG InterlockedExchange( PLONG volatile plTarget, //要赋值的变量地址 LONG lValue //要赋的值 ); 我们看一个例子: //本程序用来实验学习原子操作函数Interlocked系列函数 #include stdio.h #include stdlib.h #include windows.h #include iostream //使用C++输入输出流对象需要包含此头文件,且指定命名空间 using namespace std; long dwGlobal = 0; //用来测试的全局变量 DWORD WINAPI Thread1(LPVOID lpParam); DWORD WINAPI Thread2(LPVOID lpParam); int main(int argc, char *argv[], char *env[]) { HANDLE hThread1, hThread2; coutdwGlobalendl; hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL); coutdwGlobal after Thread1endl; hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL); CloseHandle(hThread1); CloseHandle(hThread2); //这里其实应当添加一条Wait语句来确保子线程执行退出 //Sleep(1000); //如果没有这句,主线程会在子线程运行结束前结束,结果仍然不会是2 coutdwGlobal after Thread 12endl; cout主线程结束endl; system(pause); return 0; } DWORD WINAPI Thread1(LPVOID lpParam) { coutendl线程1开始运行...endl; dwGlobal++; coutendl线程结束endl; return 1; } DWORD WINAPI Thread2(LPVOID lpParam) {

文档评论(0)

1亿VIP精品文档

相关文档