delphi 多线程2

梦想的初衷 提交于 2020-02-18 13:43:35

多线程常用的内核对象:CreateEvent事件,CreateMutex互斥,CreateSemaphore信号,CreateWaitableTimer计时器

{建立事件}
function CreateEvent(
  lpEventAttributes: PSecurityAttributes; {!}
  bManualReset: BOOL;
  bInitialState: BOOL;
  lpName: PWideChar
): THandle; stdcall;

{建立互斥}
function CreateMutex(
  lpMutexAttributes: PSecurityAttributes; {!}
  bInitialOwner: BOOL;
  lpName: PWideChar
): THandle; stdcall;

{建立信号}
function CreateSemaphore(
  lpSemaphoreAttributes: PSecurityAttributes; {!}
  lInitialCount: Longint;
  lMaximumCount: Longint;
  lpName: PWideChar
): THandle; stdcall;

{建立等待计时器}
function CreateWaitableTimer(
  lpTimerAttributes: PSecurityAttributes; {!}
  bManualReset: BOOL;
  lpTimerName: PWideChar
): THandle; stdcall;

上面的四个系统内核对象(事件、互斥、信号、计时器)都是线程同步的手段, 从这也能看出处理线程同步的复杂性; 不过这还不是全部, Windows Vista 开始又增加了 Condition variables(条件变量)、Slim Reader-Writer Locks(读写锁)等同步手段.
不过最简单、最轻便(速度最快)的同步手段还是 CriticalSection(临界区), 但它不属于系统内核对象, 当然也就没有句柄、没有 TSecurityAttributes 这个安全属性, 这也导致它不能跨进程使用; 不过写多线程时一般不用跨进程啊, 所以 CriticalSection 应该是最常用的同步手段.

------------------------------------------------------------------------------------------------------------------------------------------------------------

先介绍临界区(不是内核对象,不能跨进程):作用,独占共享资源的的访问权(同一时间内只有一个线程可以修改共享资源

更多理解祥见:http://www.cnblogs.com/760044827qq/p/4158640.html

"临界区"(CriticalSection): 当把一段代码放入一个临界区, 线程执行到临界区时就独占了, 让其他也要执行此代码的线程先等等;

var CS: TRTLCriticalSection;   {声明一个 TRTLCriticalSection 结构类型变量; 它应该是全局的}
InitializeCriticalSection(CS); {初始化}
EnterCriticalSection(CS);      {开始: 轮到我了其他线程走开}
LeaveCriticalSection(CS);      {结束: 其他线程可以来了}
DeleteCriticalSection(CS);     {删除: 注意不能过早删除}

Delphi 在 SyncObjs 单元给封装了一个 TCriticalSection 类,用法和API类似。

------------------------------------------------------------------------------------------------------------------------------------------------------------

等待函数

function WaitForSingleObject(
  hHandle: THandle;      {要等待的对象句柄}
  dwMilliseconds: DWORD  {等待的时间, 单位是毫秒;如果是INFINITE,就是一直等。}
): DWORD; stdcall;       {返回值如下:}

WAIT_OBJECT_0  {等着了, 本例中是: 等的那个进程终于结束了}
WAIT_TIMEOUT   {等过了点(你指定的时间), 也没等着}
WAIT_ABANDONED {好不容易等着了, 但人家还是不让咱执行; 这一般是互斥对象}

------------------------------------------------------------------------------------------------------------------------------------------------------------

原理分析: 互斥对象是系统内核对象, 各线程都可以拥有它, 谁拥有谁就能执行; 执行完毕, 用 ReleaseMutex 函数释放拥有权, 以让其他等待的线程使用. 其他线程可用 WaitForSingleObject 函数排队等候(等候也可以理解为排队申请).
使用过程:

var hMutex: THandle; {应该先声明一个全局的互斥句柄}
CreateMutex          {建立一个互斥对象}
WaitForSingleObject  {用等待函数排队等候}
ReleaseMutex         {释放拥有权}
CloseHandle          {最后释放互斥对象}

ReleaseMutex、CloseHandle 的参数都是 CreateMutex 返回的句柄, 关键是 CreateMutex 函数:

function CreateMutex(
  lpMutexAttributes: PSecurityAttributes;
  bInitialOwner: BOOL; {是否让创建者(此例中是主线程)拥有该互斥对象}
  lpName: PWideChar    {可以给此互斥对象取个名字, 如果不要名字可赋值为 nil}
): THandle;
{
1、第一个参数前面说过.
2、第二个参数在这里一定要是 False, 如果让主线程拥有互斥, 从理论上讲, 得等程序退出后其他线程才有机会;
   取值 False 时, 第一个执行的线程将会最先拥有互斥对象, 一旦拥有其他线程就得先等等.
3、第三个参数, 如果给个名字, 函数将从系统中寻找是否有重名的互斥对象, 如果有则返回同名对象的存在的句柄;
   如果赋值为 nil 将直接创建一个新的互斥对象; 下个例子将会有名字. }Delphi 在 SyncObjs 单元给封装了一个 TCriticalSection 类,用法和API类似。

------------------------------------------------------------------------------------------------------------------------------------------------------------

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!