分两大类:内核对象方式和用户方式。
内核对象方式:WINDOWS内核提供的可以用来进行线程同步的内核对象,都是可以发信号(Signaled)的对象,在WINDOWS中它们被称为“调度程序对象”(dispatcher object)。它们包括进程(PROCESS)、线程(THREAD)、事件(EVENT)、信号量(SEMAPHORE)、互斥(MUTEX)、时钟(TIMER)等。对这一类的对象,线程都可以通过用WaitForSingleObject()或WaitForMultpleObjects()等API来获得对象的使用权。当对象处于信号态时,线程立即返回,获得对象的使用权。当对象未处于信号态时,即对象正被其他线程占用时,线程就会被排在该内核对象的等待队列当中,当对象变为信号态时,队列中排队的第一个线程便得到该对象,被内核放入线程就绪队列,已重新获得CPU时间。在线程使用完对象后,需要释放该对象的使用权,以便其它等待该对象的线程获得执行。
用户方式:在WINDOWS下,WINDOWS还给用户提供了关键代码段(CRITICAL_SECTION),这种用户方式的线程同步解决方法。这种方式,比内核对象方式执行快。因为每次检测内核对象是否被占用时,系统都要由用户模式换为核心模式,这样就要消耗不少的切换时间。而关键代码段只是在用户模式下被简单检测是否已被其它线程占用,这样就比内核对象少了模式间切换所用的时间。在需要同步保护的代码量不是很大的情况下,使用关键代码段不失为一个好的解决方法,它可以提高代码的执行效率,减少线程间的冲突。当关键代码段发生冲突时,即一个线程检测到关键代码段已被其他线程占用时,该线程就进入等待状态。关键代码段有一个等待超时,如果超时发生时,线程仍未获得关键代码段,就会产生一个异常。所以,在编写关键代码段程序时应当注意用完后释放。关键代码段的超时值被记录在注册表的HKEY_LOCAL_MACHINE\System\CurrentControSet\Control\Session Manager键下的CriticalSectionTimeout关键字中。默认的值为2592000s,大约30天。我们可以通过改动这个值来调整超时时间,由于该值是系统公用的,所以建议设置该值时最小不要小于3S,以免影响到系统正常等待关键代码段超过3S的线程和其他应用。
操作系统之所以能够进行线程同步,主要依靠的是原子操作,原子操作是不会被打断的操作,通常它是由处理器体系结构提供,一般是由硬件支持的test-and-set操作。