• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2021-07-29 13:43 Aet 隐藏边栏 |   抢沙发  4 
文章评分 2 次,平均分 5.0

概述

  1. 在用户模式下进行线程同步的最大好处就是速度非常快。
  2. 与用户模式下的同步机制相比,内核对象的用途要广泛的多。实际上,内核对象的唯一缺点就是性能。
  3. 对线程同步来说,内核对象的每一种要么处于触发状态,要么处于未触发状态。
    Microsoft为每种对象创建了一些规则,规定如何在这两种状态之间进行转换。
    例如:进程内核对象在创建的时候总是处于未触发状态。当进程终止的时候,操作系统会自动使进程内核对象变成触发状态。当进程内核对象被触发后,它将永远保持这种状态,再也不会回到未触发状态。线程内核对象也是这样。
  4. 下列内核对象既可以处于触发状态,也可以处于未触发状态:
    1. 进程
    2. 线程
    3. 作业
    4. 文件以及控制台的标准输入流、输出流、错误流
    5. 事件
    6. 可等待的计时器
    7. 信号量
    8. 互斥量

等待函数

WaitForSingleObject

  1. 等待函数使一个线程自愿进入等待状态,直到指定的内核对象被触发为止。
    当一个线程在调用一个等待函数的时候,发现指定的内核对象已经处于触发状态了,那它是不会进入等待状态的。

    1. 第一个参数是要等待的内核对象
    2. 第二个参数是线程愿意花多长的时间等待这个内核对象被触发
  2. 如果第二个参数传INFINITE,意思是线程愿意一直等待,或者等到这个进程终止为止。

  3. 返回值

    1. 如果等待的对象被触发,返回值是WAIT_OBJECT_0
    2. 如果等待超时,返回值是WAIT_TIMEOUT
    3. 如果传入了一个无效句柄,返回值是WAIT_FAILED

WaitForMultipleObjects

  1. 是原子操作。意味着当函数检查内核对象的状态时,其他线程不能在背后修改对象的状态。
  2. 第一个参数希望检查的内核对象的数量(1~64之间)
  3. 第二个参数指向一个内核对象句柄的数组
  4. 第三个参数是希望以哪种方式使用这个函数

    1. FALSE:让线程进入等待状态直到指定内核对象中的一个被触发为止
    2. TRUE:让线程进入等待状态直到指定内核对象中的全部被触发为止
  5. 第四个参数是等待的时间长度,如果时间到了还是没触发,那么函数也会返回。
  6. 这个函数的返回值能能看出继续运行的原因
    1. 如果等待超时,返回值是WAIT_TIMEOUT
    2. 如果传入了一个无效句柄,返回值是WAIT_FAILED
    3. 如果bWaitAll传的是TRUE,并且所有对象都被触发了,那么返回值是WAIT_OBJECT_0
    4. 如果bWaitAll传的是FALSE,只要任何对象被触发,函数就会立即返回,返回值是WAIT_OBJECT_0和(WAIT_OBJECT_0 + dwCount - 1)之间的任何一个值。
    5. 换句话说,如果返回值既不是WAIT_FAILED也不是WAIT_TIMEOUT,那么把返回值减去WAIT_OBJECT_0,得到的应该是第二个参数传给函数的句柄数组的一个索引。

等待成功所引起的副作用

  1. 对一些内核对象来说,成功地调用WaitForSingleObject或者WaitForMultipleObject,实际上会改变对象的状态。
    一个成功的调用指的是函数发现对象已经被触发了,然后返回WAIT_OBJECT_0的一个相对值。
  2. 如果对象的状态发生了变化,则称之为等待成功所引起的副作用。
    假设线程正在等待一个自动重置事件对象,当事件被触发时,函数会检测到这一情况,这时它可以直接返回WAIT_OBJECT_0给调用函数。但是,再函数返回之前,它会使事件变为非触发状态(所谓等待成功所引起的副作用)。
  3. 如第2条,自动重置事件之所以会有这样的副作用,原因是Microsoft为此类对象定义了这样的规则。
    不同的对象有不同的副作用。
    有些对象完全没有副作用,比如进程、线程。

事件内核对象

事件的内容

  1. 包含一个使用计数。
  2. 一个用来表示事件是自动重置事件还是手动重置事件的布尔值。
  3. 一个用来表示事件有没有被触发的布尔值。

关于触发

  1. 事件的触发表示一个操作已经完成。
  2. 当一个手动重置事件被触发的时候,正在等待改事件的所有线程都将变成可调度状态。
  3. 当一个自动重置事件被触发的时候,只有一个正在等待该事件的线程会变成可调度状态。

事件的用途

  1. 让一个线程执行初始化工作,然后再触发另一个线程,让它执行剩余的工作。
  2. 比如一开始将事件初始化为未触发状态,然后当线程完成初始化工作的时候,触发事件。
    此时,另一个线程正在等待该事件,让它发现事件被触发后,就变为可调度状态。这时,该线程知道第一个线程已经完成了它的任务。

函数

  1. 第二个参数表示手动重置还是自动重置
    1. 手动重置TRUE
    2. 自动重置FALSE
  2. 第三个参数表示事件的触发状态
    1. 触发状态TRUE
    2. 未触发状态FALSE

  1. 第三个参数表示事件的触发状态
    1. CREATE_EVENT_INITIAL_SET表示将事件初始化为触发状态,否则为未触发状态。
    2. CREATE_EVENT_MANUAL_RESET表示将创建的是一个手动重置事件,否则将创建的是一个自动重置事件。
  2. 第四个参数允许指定在创建事件时返回的句柄对事件有何种访问权

  1. 这个函数会先触发事件然后立即将其恢复到未触发状态。(脉冲触发)
    1. 对一个手动重置事件调用,当事件被脉冲触发的时候,正在等待该事件的线程都会变成可调度状态。
    2. 对一个自动重置事件调用,只有一个正在等待该事件的线程会变成可调度状态。

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2021-11-20
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享