zoukankan      html  css  js  c++  java
  • delphi 多线程2

    多线程常用的内核对象: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类似。

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

  • 相关阅读:
    全景3d
    node.JS
    同步、异步
    必填
    this.$http.post ||this.$http.put||vue 获取url参
    硬编码转换单位||vue
    路由下二级跳转: childen 的childen
    vue侧边栏导航和右边内容一样高
    v-for v-if || v-else
    Python_Automation_04Email_smtplib
  • 原文地址:https://www.cnblogs.com/760044827qq/p/4158633.html
Copyright © 2011-2022 走看看