首页 > *nix安全, Win安全 > 线程模型对比: Windows VS POSIX

线程模型对比: Windows VS POSIX

2014年2月12日 发表评论 阅读评论 29,836次浏览    

原文:http://software.intel.com/en-us/blogs/2006/10/19/why-windows-threads-are-better-than-posix-threads

翻译:徐文博

曾使用过POSIX线程(Pthreads)和Windows线程API, 我认为Windows线程具有更好的编程模型。虽然它们都能创建、销毁线程,并协调线程间的交互,但windows线程API更易使用并且设计优雅。这是多线程开发、维护者的思考视角。下面让我来举例说明。

简单的数据类型

在Pthreads中,每个对象均有其自己的数据类型(pthread_t, pthread_mutex_t, pthread_cond_t 等等)而在Windows线程中,仅有一种类型:HANDLE。这就意味着在Pthreads中,需要使用不同的函数来处理每种对象类型。阅读理解他人所写的Pthreads代码可能会比较简单,但这要求编程人员必须知道不同函数的参数个数、顺序以及类型。相反的,在Windows线程中,因为不同对象使用了同种数据类型,它们就有了统一的Create*函数和各自针对性的Release*函数。

或许使用单对象数据类型的最大好处就是仅需WaitForSingleObject函数就能阻塞那些等待某对象的线程。所以,不管代码是在等待线程、互斥量、信号量,还是事件,我们只需知道一组参数即可。与此相关联的函数WaitForMultipleObjects,同样地简单易用,并且较好的解决了Pthreads中等待多线程结束时需要依次调用pthread_join的问题。或许有人会说不同的对象使用相同的数据类型容易导致使用WaitFor*时的混淆。而这可以通过编程人员遵循见名知义的原则解决,为句柄清晰的命名,表明代码是在等待线程结束,事件触发还是互斥量的释放。

WaitForMultipleObjects的功能

仅调用一次WaitForMultipleObjects函数,就能阻塞等待多线程结束的线程,此外也可以等待任意多个线程的结束。也就是说,即使只有一个线程结束了,也可以设置WaitForMultipleObjects函数返回,并表明哪个线程触发了。如果当线程结束时,需要依据线程的身份进行特定的清理环节,那就可以在等待其他线程返回前完成。这种清理环节可以在线程结束后,以最有效的顺序完成,而不管发生的顺序是怎样的。Pthreads同样可以实现类似的清理过程,但需要以既定的顺序等待线程的结束。所以,即使最后一个线程先结束了,它还是需要等待前面线程的清理工作的结束。

因为不同的对象都使用了HANDLE这种类型,所以可以调用WaitForMultipleObjects来等待线程、互斥量、信号量、事件的任意组合。这种特性为编程人员提供了Pthreads所不能提供的便利。比如,我写了一段代码,使用数组存放线程和事件句柄,供线程查询数据。方案是如果找到了对象,同时查询线程也终止了,就唤醒阻塞线程;如果对象未找到,就直接终止查询线程,并不触发事件。通过等待任一触发WaitForMultipleObjects返回的句柄,不管是否成功查找到,当查询线程结束时,简单的switch语句就可以确定对象是否已经找到,也能做些后续处理。

信号的持久性

来看看Pthreads中的一个经典难题:如果一个线程通告某个条件变量可用了,却没有其他线程等待在该资源,那么这有意义吗? 如果没有线程等待这些条件变量,信号就丢失了。因此,有必要设置一个while循环来检测用于触发信号的条件表达式,它需要一个互斥量来保护条件表达式中的数据以及数据的更改,这甚至可以避免线程的假唤醒。

而对于Windows线程,如果事件处于signaled状态,它就保持在signaled状态。打个比方,一颗树倒了,它会不断的尖叫直到有人过来。Windows事件从signaled到unsignaled状态的正确转换可由编程人员来确保。这其中涉及到对事件属性的正确设置,以及必要的手动事件重置。总之,这似乎更简单方便。此外,一旦触发事件所需的条件具备了,还可以再次触发。而在Pthreads中,这样的机会稍纵即逝,错过就错过了。

这就是我认为Windows线程优于Pthreads线程API的原因。你说呢?你是否还有喜欢Windows线程的其他原因?或者你认为Pthreads更好?期待倾听你的选择。

(全文完)

版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
  1. 本文目前尚无任何评论.