一、用户方式同步:同步速度非常快。
互锁函数家族只能在单值上运行,根本无法使线程进入等待状态。可以使用关键代码段使线程进入等待状态,但是只能用这些代码段对单个进程中的线程实施同步。还有,使用关键代码段时,很容易陷入死锁状态,因为在等待进入关键代码段时无法设定超时值。
二、使用内核对象来实现线程的同步:内核对象机制的适应性远远优于用户方式机制。实际上,内核对象机制的唯一不足之处是它的速度比较慢,因为调用内核对象时,调用线程必须从用户方式转为内核方式。
事件内核对象:当一个线程执行初始化操作,然后通知另一个线程执行剩余的操作时,事件使用得最多。M i c r o s o f
t为自动重置的事件定义了应该成功等待的副作用规则,即当线程成功地等待到该对象时,自动重置的事件就会自动重置到未通知状态。通常没有必要为自动重置的事件调用R e s e t E v e n t函数,因为系统会自动对事件进行重置。但是, M i c r o s o f
t没有为人工重置的事件定义成功等待的副作用。
等待定时器内核对象:在某个时间或按规定的间隔时间发出自己的信号通知的内核对象。它们通常用来在某个时间执行某个操作。
互斥对象内核对象:能够确保线程拥有对单个资源的互斥访问权。互斥对象的行为特性与关键代码段相同,但是互斥对象属于内核对象,而关键代码段则属于用户方式对象。这意味着互斥对象的运行速度比关键代码段要慢。但是这也意味着不同进程中的多个线程能够访问单个互斥对象,并且这意味着线程在等待访问资源时可以设定一个超时值。互斥对象不同于所有其他内核对象,因为互斥对象有一个“线程所有权”的概念。其他内核对象中,没有一种对象能够记住哪个线程成功地等待到该对象,只有互斥对象能够对此保持跟踪。
信号量内核对象用于对资源进行计数。信号量的功能比互斥量要大。调用
HANDLE hsem = CreateSemaphore(NULL, 1, 1, NULL); 产生的信号量可以代替mutex的作用并且比mutex更好使,因为信号量可以在一个线程中得到,而在另一个线程中释放。(详解如下)
互斥量与信号量之间最大的区别在于:互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。互斥对象包含一个使用数量,一个线程I D和一个递归计数器。
ID用于标识系统中的哪个线程当前拥有互斥对象,递归计数器用于指明该线程拥有互斥对象的次数。通过调用一个等待函数,并传递负责保护资源的互斥对象的句柄,线程就能够获得对共享资源的访问权。在内部,等待函数要检查线程的I
D,以了解它是否是0。如果线程I D是0,那么该线程ID被设置为调用线程的ID,递归计数器被设置为1,同时,调用线程保持可调度状态。如果等待函数发现ID不是0,那么调用线程便进入等待状态。系统将记住这个情况,并且在互斥对象的ID重新设置为0时,将线程ID设置为等待线程的ID,将递归计数器设置为1,并且允许等待线程再次成为可调度线程。上述细节可以解释为什么互斥量的加锁和解锁必须在同一个线程中。因为加锁的时候记录了拥有该资源的线程的id,如果在另一个线程中解锁,这个线程目前根本不拥有该资源,解锁肯定失败。
阅读(1381) | 评论(0) | 转发(0) |