Pthreads vs Win32 threads 385
An anonymous reader writes "It's interesting when different people have different opinions. While I was searching for something on Intel's website, I came across an article on why Windows threads are better than Posix threads. Curiously, I also came across this article on why Posix Pthreads are better that Win32 threads. The thing is, both of these articles are written by the same author!
So who is right (metaphorically speaking?), or what has changed since the first article was written?"
So who is right (metaphorically speaking?), or what has changed since the first article was written?"
switch? (Score:2, Interesting)
Re:better yet (Score:2, Interesting)
Re:Look at the dates, Dude. (Score:5, Interesting)
Normally I'd agree with you. But if you read both articles, you realize that his intentions may be a bit less honorable. The Win32 article is the exact same article, but with the conclusions changed. Maturing opinions usually result in some discussion of why one has changed their mind (even if it's only mentioned in passing) and/or a deep explanation of what caused their mind to change. This smells more like an attempt to play both sides.
Of course, it could be that the author is simply not comfortable with writing. He could be looking to make a quick buck by taking a simple forum post of his and modifying it to reflect his current opinion. It's worth giving him the benefit of the doubt on, but I am certainly suspicious.
Re:switch? (Score:2, Interesting)
After reading both entries, I went to close the tab and was given a chance to provide feedback on intel's site. After clicking on all the survey questions, I left this comment:
[tt]
there are differences, but not _that_ many (Score:5, Interesting)
That said, I find it quite creepy that this guy wrote these two articles with extremely similar wording for his introductions, making the exact opposite points. It is very strange. I wonder what his motivation was.
Re:PThreads is better (Score:3, Interesting)
Not strictly true. It is possible to build condition variables for Windows (Windows has Semaphores after all, which can be used to make just about anything), but the Windows threading model makes doing so far from easy. Please note that I'm not defending WinThreads, however, so much as clarifying this particular issue.
Re:PThreads is better (Score:3, Interesting)
Personally, I've found situations using each API where the functionality desired was very difficult to replicate in the other API. It usually requires some rethinking, is all. And, last I checked, there were things you could do in either API that weren't easily reproducable in the other API.
However, both APIs tend to evolve towards each other over time so it becomes less of an issue.
win32 equivalent for pthread_cond_wait? (Score:3, Interesting)
What is the right way to do a pthread_cond_wait under win32?
Re:Eeew, threads. (Score:3, Interesting)
Not just Linux.
I think this was the case with SVR4 and BSD4.3.
But that was a LONG time ago... memory gets fuzzy..
It's entirely probable that the first time I read about fork being copy-on-write was in Tannenbaum's yellow book, so it might even be in Minix.
It has certainly been the case as far as I'm aware in every non-toy Unix and UNIX for at least a decade.
But then again, I don't care, since I'm not a kernel developer.
Re:PThreads is better (Score:5, Interesting)
It's not so cut and dry. I use a library I wrote to abstract away PThreads and Win32 Threads to give me a multi-platform interface, but I would say that each side has their upsides and downsides.
With pthreads, there's no way to combine socket i/o and thread notification. In Win32, I can have a thread waiting on both a socket and an event at the same time, allowing me to cleanly signal I/O blocked threads. This isn't the case with pthreads.
However, Win32 REALLY needs a way to handle negative mutexes (ie. taking more than one resource from a mutex at a time). I had to write my own, and it was a serious pain to make sure I didn't have any race conditions. All the articles I've seen on Win32 equivalents had race conditions, and that means that there means that there are probably developers trusting multi-threading primitives that they really shouldn't be./p>
Re:pthread is straightforward ? (Score:2, Interesting)
If you think the pthread API is "bloated", or unintuitive for simple tasks, I'm going to have to go ahead and say you're a troll.
Bloated? On a Linux box I happen to have handy, libpthread.a is 208Kb.
Hard to use for simple tasks? Perhaps all of the *_init() functions are a bit daunting to the eyes. But does the Wikipedia article's [wikipedia.org] example really look that bad?
I first used the pthread interface when I was only 15 years old. Even though I didn't fully understand the consequences of parallelization back then, I didn't feel like the library itself was enourmously comlex. I was able to whip out multi-threaded socket programs pretty quickly. Later I used Win32 threads. I found it to be basically the same.
I'm surprised more of the people complaining about the lack of WaitForMultipleObjectsEx() haven't mentioned POSIX semaphores. I saw one post about them, that's it.
Re:Eeew, threads. (Score:3, Interesting)
Re:PThreads is better (Score:5, Interesting)
You are talking mostly bollocks, probably because you don't program using the Windows API
And PThreads also gives you a fixed set of primitives. In some respects they are more powerful, in others they are weaker. This is a bullshit strawman.
WTF?
That brings me to the next point: in Unix there is no wait to wait on multiple synchronization primitives (as opposed to FDs) at once, and only a few primitives support a timed wait. In Windows you have WaitForMultipleObjectsEx [microsoft.com]. Look it up.
Let me be clear on the difference: in Windows the scheduler API for waiting on IO and synchronization primitives is fully integrated - you can wait on any combination of IO and sync objects in the same Wait call. You must of course be using Windows Async IO which uses Events rather than FDs as the waitable object. Under *nix you can wait for multiple condition variables, or multiple file descriptors, or a single mutex / thread / process. There is no way to link an FD to a condition variable.
In Windows you have Mutexes, Events and Semaphores. Events alone are sufficient to provide almost identical functionality to condition variables. You may have missed that memo.
I say "almost identical" because the underlying scheduler behaviour is slightly different, which makes it very difficult to perfectly emulate Pthreads on Win32. Read Strategies for Implementing POSIX Condition Variables on Win32 [wustl.edu].
Cough. Bullshit. Cough. Read Porting of Win32 API WaitFor to Solaris Platform [sun.com] to get a clue. It is possible to build Pthreads on top of Win32, and vice versa. Neither emulation is particularly efficient though.
The complaint about weakness in the Win32 scheduling API means that the author is using it incorrectly.
Re:better yet (Score:3, Interesting)
Except that Win32 threading model only works on X86 (since it needs Win32, which only runs on X86), while Pthreads work everywhere. Pthreads therefore mean more competition for Intel, since the program using them can be made portable.
MSFT POSIX (Score:3, Interesting)
Windows has fork(), as well as all the other POSIX calls.
Originally, Windows NT had 4 separate APIs: the NT API, Win32, POSIX, and OS/2. The NT API was (and still is) the one used by the kernel. It has all the capabilities necessary to support the other three, and is never (well, rarely at least) used directly by applications. Win32 was, at the time, very new and hadn't seen wide use--it was designed as the primary API for Windows 95, and Microsoft wasn't yet sure whether it would catch on in the NT world.
The other two APIs have the same level of explicit support in the kernel as Win32, but there's a catch: you have to pick which subsystem you want to use for a given application. Win32 programs can't make calls to the POSIX subsystem, nor vice-versa. Over time, it became clear that only Win32 was being used for NT programming, and the other two APIs disappeared. The OS/2 API is, as far as I know, completely unavailable for modern versions of NT (i.e. 2000, XP, and Vista), while the POSIX API is still supported, but isn't available by default.
Check out Windows Services for Unix [microsoft.com]. This packages installs (and uses) the NT POSIX API.
For more information, read Microsoft Windows Internals [microsoft.com]
A Diff view (Score:2, Interesting)
Re:A Diff view (Score:2, Interesting)
1c1
I've used both POSIX threads (Pthreads) and Windows threads APIs, and I believe that Windows has the better programming model of the two. While each threading method can create threads, destroy threads, and coordinate interactions between threads, the reason I make this claim is the simplicity of use and elegance of design of the Windows threads API. This is all from the perspective of multithreaded code developers or maintainers. Let me illustrate with a few examples.
3c3
Simplicity of data types. In Pthreads, each object has its own data type (pthread_t, pthread_mutex_t, pthread_cond_t, etc.) while, in Windows threads, there is pretty much just the one type: HANDLE. For Pthreads this means different functions are used for working with each object type. Reading and understanding Pthreads code written by someone else can be straightforward. However, this does mean that the programmer must know the number, order, and type of parameters for all the different functions. On the other hand, because of the use of the same type for different objects, there is a Create* function for each different object and a corresponding Release* function for most.
5c5
Perhaps the biggest advantage of a single object data type is that there is only the one function needed to make a thread block while waiting for an object: WaitForSingleObject. Thus, only one set of parameters needs to be known regardless of whether the code is waiting on a thread, a mutex, a semaphore, or an event. The related function, WaitForMultipleObjects, is just as simple to use and easily overcomes the problem of needing to wait for multiple thread terminations one function call at a time (pthread_join) that Pthreads requires. While some may say that using a single data type for many different objects can lead to confusion when used in WaitFor* calls, programmers should set the name of the handle such that it is readily apparent whether the code is expecting a thread termination, an event to be signaled, or a mutex to be released.
7c7
WaitForMultipleObjects functionality. Besides being able to block a thread waiting for multiple thread terminations in a single call, the programmer can actually wait for any out of a set of threads to terminate. That is, even when only one thread has completed, the WaitForMultipleObjects function can be set to return and indicate which thread triggered the return. If there is specific "clean up" processing that depends on the identity of the thread that finished, this can be done before returning to wait on the remaining threads. This clean up processing will be done in the most efficient order possible, soon after each thread terminates, no matter in what order this happens. Pthreads can perform similar post-processing, but will need to wait for the threads to terminate is some fixed order. So, even if the last thread finishes first, it must wait for all the post-processing of the previous threads to be completed.
9c9,15
Because different objects all use the HANDLE type, a call to WaitForMultipleObjects can be set to wait for any combination of threads, mutexes, semaphores, and/or events. This feature can give the programmer a flexibility that cannot be easily (if at all) duplicated in Pthreads. As an example, I've written Windows code that used an array to hold both thread and event handles to support a threaded search through data. The ideas was to signal the blocking thread if the item being looked for was found and when the searching thread terminated; if the object was not found, the searching thread terminated without setting the event. By waiting for either handle to cause WaitForMultipleObjects to return, a simple switch statement could determine if the item had been found (and process the data) plus perform some post-processing computation upon the termination of the searching thread (regardless of whether the search was successful).
>
> Persistence of signals. To paraphrase a classic conundrum in terms of
Re:quothe the poster (Score:5, Interesting)
To the contrary. I work on Linux systems at work, and play on Windows, using
C//
Re:Eeew, threads. (Score:5, Interesting)
I ended up writing the whole thing using forks and no pthreads. My code was then subjected to a code review and one of the questions that came up in the review meeting was why I used fork and didn't do the implementation in pthreads. My arguement was one of complexity. I was challenged with the "fork is old technology, you should have used pthreads" and my response was "My implementation is easy to understand, oh and by the way, it works!"
Needless to say, my code has been in production for about a year and a half with no issues. I'm sure someone smarter than me could have wrote the whole using pthreads, but I'm just not sure what it would have gained them other than a slightly smaller memory footprint but at the price of increased complexity.
Re:quothe the poster (Score:2, Interesting)
When it comes down to it, I find I'm able to most quickly create a pleasant GUI app in Visual Studio, using
Re:Eeew, threads. (Score:4, Interesting)
Running as root and want to start the process with lower privileges? Do fork - setuid - exec. Want to open pipes to the child? Do pipe - fork - a couple calls in the child to connect the pipes to stdin/out - exec.
By contrast, Windows has to encapsulate anything you want to be able to do to set up the child's environment in the CreateProcess call. That's why it takes 9 arguments, one of which is a flags argument where there are 15 flags, and one of which is a pointer to a struct with 17 fields (one of which takes another 9 flags).
Re:quothe the poster (Score:2, Interesting)
My hope is that one day Java becomes as good. It certainly has the potential.
Re:win32 has 1 thing i want pthreads to have (Score:1, Interesting)
Detached threads avoid this issue, and is the solution adopted by Mozilla for their cross-platform threading needs. It means you can't just return from a thread sensibly, but they make the conscious choice not to rely on this behavior.
While I'm sure the Windows way is convenient in some sense, I don't find the POSIX model deficient in any sense. Thread cancellation is a related issue as to why waiting for threads to exit is somewhat silly. Threads should signal when they've completed work, and you should be watching/waiting for this, not simply joining on threads waiting for them to terminate.
It's even easy enough to build a data type/procedure to do all this for you in just a few steps.
Re:Look at the dates, Dude. (Score:3, Interesting)
1) These arguments have no rational basis, and both are BS (unjustified opinions).
2) There are serious factual errors in at least one article.
I wonder which one of these is closer to the truth? I'm guessing it's #1. Either way, the author can no longer be taken seriously.
Re:Eeew, threads. (Score:3, Interesting)
Imagine a Perl program, which requires about 35 MB of memory (25 MB for the parsed code, 10 MB for actual work). The user wants to run 6 instances of the program. Without fork (that is, on Windows) the user will need 210 MB of memory. On Unix I can use fork() and the user will only need about 100 MB of memory because the parsed code is shared between instances.
This is not a hypothetical situation, I actually have a program that fits this description. A GNOME developer also recently developed a Python script which preloads PyGTK and forks instances, to save memory in PyGTK apps.
fork() is also ideal for making a "protected copy" of your program. Suppose that you have a web server which forks when a new client connected. If the child process crashes then it won't affect the parent process or the other children. I don't think you can do that in Windows easily.