表格中描述的是常用的同步机制,这些机制的相关描述以及他们在windows系统下面的实现。
同步方法 |
描述 |
Windows下的机制 |
Interlocked operations |
提供原子的算术,逻辑,和列表操作,不仅是多线程安全的同时也是多处理器安全的 |
InterlockedXxx and ExInterlockedXxx routines |
Mutexes |
提供内存的互斥访问权限 |
Spin locks, fast mutexes, kernel mutexes, synchronization events |
Shared/exclusive lock |
运行一个线程专享写多个线程共享读 |
Executive resources |
Counted semaphore |
允许固定大小的获取权限 |
Semaphores |
一个互斥体保证共享资源的专有访问权限,任意能够保证互斥专有权限的锁都能被认为是互斥体。比如,自旋锁和同步事件都可以被认为是互斥体,因为当一个同步事件被唤醒的时候,仅有一个线程能够获取访问权限,同样自旋锁在并发条件下最多只能有一个线程能够被选中执行。互斥体的类型依赖于互斥体的使用环境,选择互斥体需要遵循下列规则:
1 互斥体可以运行的IRQL级别,也就是互斥体可以在哪一级IRQL当中获取和释放
2 获取互斥体是否会提升当前的IRQL?如果IRQL得到提升,那么原来的IRQL被保存在哪里?
3 是否互斥体的释放和获取必须在同一个线程环境上下文当中?
4 互斥体是否能够被递归获取,也就是说一个线程能否在不释放互斥体的条件下,再次获取该互斥体?
5 当一个持有互斥体的线程被终止而没有释放互斥体会出现什么情况?
互斥体类型 |
IRQL限制 |
递归和线程方面的细节 |
Interrupt spin lock |
获取的时候提升IRQL到DIRQL并且返回之前的IRQL给调用者 |
不能递归获取,获取和释放在同一个线程上下文 |
Spin lock |
获取的时候提升IRQL到DISPATCH_LEVEL并且返回之前的IRQL给调用者 |
不能递归获取,获取和释放在同一个线程上下文 |
Queued spin lock |
获取的时候提升IRQL到DISPATCH_LEVEL并且保存之前的IRQL在一个锁持有者句柄当中 |
不能递归获取,获取和释放在同一个线程上下文 |
Fast mutex |
获取的时候提升IRQL到APC_LEVEL并且保存之前的IRQL到锁当中 |
不能递归获取,获取和释放在同一个线程上下文 |
Kernel mutex (a kernel dispatcher object) |
在获取的时候进入代码互斥区域,在释放的时候离开代码互斥区域 |
可以递归获取,获取和释放在同一个线程上下文 |
Synchronization event (a kernel dispatcher object) |
获取并不会改变IRQL,在小于等于APC_LEVEL级别等待,而在小于等于DISPATCH_LEVEL级别激发 |
不能递归获取,获取和释放不需要在同一个线程上下文 |
Unsafe fast mutex |
获取的时候不改变IRQL并且在小于等于APC_LEVEL级别下面释放 |
不能递归获取,释放和获取在同一个线程上下文 |
Windows同步机制 |
描述 |
IRQL限制 |
InterlockedXxx routines |
在换页内存上执行原子的算术和逻辑运算 |
能够在任何IRQL当中获取 |
Spin locks |
在非换页内存上提供专享的内存访问 |
在IRQL <= DISPATCH_LEVEL级别上获取 |
ExInterlockedXxx routines |
执行算术、逻辑和列表控制的原子操作,不仅是多线程安全的同样也是多处理器安全的 |
在IRQL <= DISPATCH_LEVEL级别上访问 SList 历程; 其他历程可以在任意IRQL上面访问 |
Fast mutexes |
在APC_LEVEL级别保护数据,同时防止线程被打断 |
在IRQL <= APC_LEVEL级别上获取 |
Executive resources |
允许一个线程专享写而其他的线程共享读 |
在IRQL<=APC_LEVEL级别上获取 |
Kernel dispatcher objects (events, kernel mutexes, semaphores, timers, files, threads, processes) |
在IRQL<=APC_LEVEL级别上提供不同形式的同步,能够和用户模式下的应用程序同步 |
在 IRQL <= APC_LEVEL下等待; 在IRQL <= DISPATCH_LEVEL下激发 |
Callback objects |
在IRQL<=DISPATCH_LEVEL内核模式下面提供代码同步,能够用于驱动之间同步 |
在 IRQL <= DISPATCH_LEVEL被通知; 回调例程运行在激发线程的上下文当中,和激发线程的IRQL一样 |
自旋锁和它的名称所暗示的一样:当一个线程拥有自旋锁的时候,其他的线程在内存的某一个位置上通过忙等待自旋,直到锁是可用的。也就是说线程并不会阻塞,而是继续保持CPU的控制权,以防止执行相同或者更低IRQL中的代码。自旋锁是一个没有完全公开的