• 0

Windows' faulty multithreading system?


Question

Not sure if this thread belongs here, but anyways.

This guy, who was my Java tutor, claimed that the way Windows manages processes is sub par relative to Linux's multithreading.I didn't ask him for more explanation and as such he didn't go into details, but claimed that the processes in Windows are in fact threads that belong to one mother process and that is why-to his belief- Windows programs are subject to crashes that may bring the whole OS down.He said in Linux it is real multithreading and processing.

He reminded me of those Windows Media Player hangs when a crappy CD is inserted into the drive that often lead to most of the OS functions turning 'unresponsive'.Or IE lockups for that matter.

Funny thing though, is that I tried to reproduce the same problem in Kubuntu with Amarok 2 and it was even worse in another respect: When the cd was ejected, Amarok remained unresponsive forever so I had to close it manually.

That's in contrast with WMP where it resumes functioning as soon as the malformed CD is out the drive.

Also Vista doesn't seem to suffer from such issues.

Although, in a try to prove his point, he told me and my classmates to run this java code in both OS'es."This code should expose the faulty multithreading system of Windows."That's what the tutor claimed.

Here's the code:

//The Main class that execute the thread objects.
public class Main{
	public static void main(String args[]){
		Thread Tping=new Thread(new Ping());
		Thread Tpong=new Thread(new Pong());
		Tping.start();
		Tpong.start();
		try{
		Tping.sleep(1000);
		Tpong.sleep(1000);
		}catch(InterruptedException e){
		System.out.println("Exception occurred!");
		}
	}
}

//The Ping class, one of the threads.
public class Ping implements Runnable{
	public void run(){
		while(true){
			System.out.print("Ping");
		}
	}
}

//The other thread, Pong.
public class Pong implements Runnable{
	public void run(){
		while(true){
			System.out.print("Pong");
		}
	}
}

Try running this program in both Linux and Windows.I did it a while back, and I think the fault that the guy was suggesting came up when I moved the console winow or clicked in it ;The constant flux of "ping pong" was interrupted, that is the 'ping' suddenly shown up in the flow of 'pong' or vice versa.

In Linux, I didn't notice such phenomena, but I can't be sure.

So try it for yourself and see what comes out.

In any case, does it prove his point of a faulty multithreading in Windows?

edit- corrected the code mistake.

Edited by Aquarian
Link to comment
Share on other sites

Recommended Posts

  • 0

Okay.Thank you Dr_Asik and also Brandon Live for the great posts and info.

I will wait and see what program the tutor will come up and then let you know.As said, he only wants to know why the program works differently on Linux and Windows.

Link to comment
Share on other sites

  • 0

One of the first things that they taught us when learning multi-threaded programming was that the duration and times that threads are run are, essentially, random as far as the programmer is concerned. Aquarian, I'm surprised that they would teach you threading and not something fundamental like that.

Link to comment
Share on other sites

  • 0

i really would switch tutors. Multi-threading is a very complex thing and hard to do right, and obviously this tutor knows nothing about it.

Link to comment
Share on other sites

  • 0
i really would switch tutors. Multi-threading is a very complex thing and hard to do right, and obviously this tutor knows nothing about it.
That's a bit harsh, everyone makes mistakes. The guy seems open to intelligent discussion from what we've seen, and that's the most important thing. I didn't really understand what he was trying to prove, I would suppose he in fact knows very well about the way threads are scheduled.
Link to comment
Share on other sites

  • 0
and supported pre-emptive multitasking (another thing Mac OS lacked for a long, long time).

And yet it was something that the Amiga had nearly a decade earlier!

Link to comment
Share on other sites

  • 0
That's a bit harsh, everyone makes mistakes. The guy seems open to intelligent discussion from what we've seen, and that's the most important thing. I didn't really understand what he was trying to prove, I would suppose he in fact knows very well about the way threads are scheduled.

my apologies if it came over a bit too harsh. However, I stand by my point, the fact that he says the ping-pong output should be in any particular order proves to me he doesn't know what multi-threading is about. I can't blame him, it is a very complex subject and I know more people who mess up completely when threading an application. But you shouldn't try to teach something about a subject which you know little about. At least do some research first before making wild claims.

And to some people who say you should program in c++ if you want to understand threading, sorry you are wrong, the principles of threading remain the same, whether you are using a managed language or c++ or even assembler. I do agree though that c++ can be a eye-opener on many things, and it certainly makes you appreciate the existence of managed languages. That said, i still do enjoy the times I have to program in c++. It gives me a superior feeling when all is done :p

Link to comment
Share on other sites

  • 0
One of the first things that they taught us when learning multi-threaded programming was that the duration and times that threads are run are, essentially, random as far as the programmer is concerned. Aquarian, I'm surprised that they would teach you threading and not something fundamental like that.

I dunno, maybe we got points mixed up here? Perhaps when the tutor read Dr_Asik's post about thread's executing-time being out of programmer's control, he thought what Dr_Asik meant was that a thread will completely stop and 'will die' when OS decides so, while Asik was actually talking about the state of thread being alive or sleeping.Yeah, quite possible that was the reason he didn't get Asik's definition of running-time.A thread is said to be still executing (it's started)even when it's sleep, but not dead yet and the tutor knows that.

I'm sure the tutor knows pretty well how threads work.The last time I saw him on wed, he told me about a project which he and a number of other programmers had to deal with years ago (perhaps pre-NT), and the goal was to write a program for a ah splitter? can't remeber the device name.It had to be done on Windows though.He complained that the thread system was messy and gave them a headache until they had the program finally up and running.

But whether the guy was a good tutor or not, is irrelevant.Because unless I choose to study Java as the next semester's course(that I won't be doing), some C# guy will be replacing him.

But you shouldn't try to teach something about a subject which you know little about. At least do some research first before making wild claims.

That, I agree with as a rule of thumb.

Also, I have only scratched the surface of programming especially OOP.Actually I amongst my classmates have been exploring basics of Java until now and didn't get into the depths of it.

Edited by Aquarian
Link to comment
Share on other sites

  • 0
he only wants to know why the program works differently on Linux and Windows.
They each have their own schedulers and the implementation is a bit different, IIRC it's slightly more complex on Windows. Whether one can be said to be better than the other, I really have no idea. I'd be surprised if there was any serious flaw in that regard on Windows, the NT kernel is nothing to sneeze at.
Link to comment
Share on other sites

  • 0
It appears that Snow Leopard will finally reach multi-threaded capaibilities rivaling Windows 2000 (with Grand Central offering functionality comparable to the NT thread pool and such).

I'm familiar with the concept of threads pool but have always seen it discussed as a pattern—language and platform agnostic in the same way that 'locks' and 'observers' are. Can you please go into detail about what kernel features NT* offers that other operating systems don't? When I'm tasked with writing threaded code I'll lean on one of the many libraries/frameworks to handle that so the idea that there's some sort of kernel magic that exists below all that is intriguing.

I'm assuming you're not talking about System.thread(ing?) or an equivalent because you specifically mention the kernel.

It's been a long time since I've touched Windows and I'd like to know more about the things you're describing.

Protected memory is separate from threading, though. Windows 95 supported multi-threading support via the Win32 API. Its implementation wasn't as robust or scaleable as NT, but it worked, and supported pre-emptive multitasking (another thing Mac OS lacked for a long, long time).

Apple had that in 1988 - nobody seemed to want it for one reason or another. Too expensive? Terrible experience? Crumby hardware? Generally pointless (who needs a UNIX system with pretty UI?). That's another discussion.

Link to comment
Share on other sites

  • 0
They each have their own schedulers and the implementation is a bit different, IIRC it's slightly more complex on Windows. Whether one can be said to be better than the other, I really have no idea.

Quoted for emphasis. Do watch out for when people say a certain scheduler is better: typically it will favor one scenario (such as latency) over another. A desktop user has entirely different needs than an embedded developer.

The only interesting thing I have to add to the discussion is I'm a fan of the lighter weight processes that UNIX tends to use. Threads let you accomplish the same thing, but I like the benefit of separate address spaces, just in case something goes drastically wrong in one process. Though, it can be harder to control subprocesses.

Link to comment
Share on other sites

  • 0
I'm sure the tutor knows pretty well how threads work.The last time I saw him on wed, he told me about a project which he and a number of other programmers had to deal with years ago (perhaps pre-NT), and the goal was to write a program for a ah splitter? can't remeber the device name.It had to be done on Windows though.He complained that the thread system was messy and gave them a headache until they had the program finally up and running.

More likely he had a headache because he didn't have the appropriate background in programming / multi-threaded design to accomplish the task, and decided he'd feel better (or look better) if he blamed the difficulty on someone else.

From a design perspective, threading generally works the same way on any Windows or *nix-based system, even including pre-NT Windows. The main differences are in the efficiency of the scheduler and the ability of the system to scale when given many CPUs to distribute threads across. NT has genearlly excelled here and used to be light years ahead of Linux. Linux has since done a fair job catching up (especially if you use some of the very latest but less stable stuff) over recent years, and there are likely cases where any given OS has particular advantages given a specific workload. But there's certainly no basis for claiming Windows' threading model or scheduling support is inferior. Quite the contrary, in fact.

Edited by Brandon Live
Link to comment
Share on other sites

  • 0
I'm familiar with the concept of threads pool but have always seen it discussed as a pattern?language and platform agnostic in the same way that 'locks' and 'observers' are. Can you please go into detail about what kernel features NT* offers that other operating systems don't? When I'm tasked with writing threaded code I'll lean on one of the many libraries/frameworks to handle that so the idea that there's some sort of kernel magic that exists below all that is intriguing.

I'm assuming you're not talking about System.thread(ing?) or an equivalent because you specifically mention the kernel.

It's been a long time since I've touched Windows and I'd like to know more about the things you're describing.

A thread pool is basically a set of worker threads that get recycled for various tasks. Some people implement their own, but generally thread pools are most advantageous when the system can manage them. Threads, like most any resource, have an overhead associated with them. Thread pools reduce the overhead of both creating/destroying threads, and other overhead by doing things like combining the wait operations of various threads into a single monitor thread, to reduce the number of context switches that result in just polling some wait criteria.

Windows 2000 introduced the NT thread pool as part of the developer API. Mainly this is exposed via the QueueUserWorkItem function. You can read general information about thread pools on MSDN here, or read about the NT thread pool (which was overhauled a bit in Windows Vista) here.

Link to comment
Share on other sites

  • 0
Quoted for emphasis. Do watch out for when people say a certain scheduler is better: typically it will favor one scenario (such as latency) over another. A desktop user has entirely different needs than an embedded developer.

The only interesting thing I have to add to the discussion is I'm a fan of the lighter weight processes that UNIX tends to use. Threads let you accomplish the same thing, but I like the benefit of separate address spaces, just in case something goes drastically wrong in one process. Though, it can be harder to control subprocesses.

On that note, I actually found out something very interesting. I was recently working on some C code on Windows and decided to parallelize it. Doing some research, I found out that there is no fork() method on Windows. There is only CreateProcess(), which is a combination fork()/exec() which creates a new process without copying the current process?s state and instead runs a specified executable. This does impose certain restrictions on what a programmer can do, although the argument could be made that fork() is to expensive that it become unnecessary without exec().

Now, I know that this is a topic about multi-threading, but perhaps this is what the tutor is referring to. It?s pretty easy to confuse threads/processes when you haven?t used them for a while, and I would think doubly so when working in Java for so long (I?m not even aware of a way to spawn a new process in Java).

Link to comment
Share on other sites

  • 0

Don't know if anyone's mentioned this yet or not, but the constant "ping-pong ping-pong" is NOT the desired behavior and it happening in linux is mostly by luck or how the threads are being scheduled by the scheduler. Actually, in the test program, there is no inherent "desired" behavior.

Try running the same program on a multi-processor machine in linux and under heavy usage and you should see different results.

Possible scenario:

CPU 1: Handles thread ping

Will see ping printed out

thread ping sleeps

CPU 2: Running program x

program x makes I/O call

CPU1: Program x's I/O call completes and now program x is running on CPU 1

CPU2: Program y runs and then finishes

CPU1: Program x is running

CPU2: Thread ping resumes. Prints out ping. Sleeps

CPU1: Thread pong runs. Prints out pong. Sleeps

CPU2: Thread ping resumes. Prints out ping. Sleeps

In this case, you can have ping ping pong ping or ping ping ping pong

On that note, I actually found out something very interesting. I was recently working on some C code on Windows and decided to parallelize it. Doing some research, I found out that there is no fork() method on Windows. There is only CreateProcess(), which is a combination fork()/exec() which creates a new process without copying the current process’s state and instead runs a specified executable. This does impose certain restrictions on what a programmer can do, although the argument could be made that fork() is to expensive that it become unnecessary without exec().

Now, I know that this is a topic about multi-threading, but perhaps this is what the tutor is referring to. It’s pretty easy to confuse threads/processes when you haven’t used them for a while, and I would think doubly so when working in Java for so long (I’m not even aware of a way to spawn a new process in Java).

Yes, windows doesn't have a fork command, that's completely a linux thing, and a C thing at that. Java doesn't even have the capability to fork, even under linux.

Java does have the capability to spawn child processes.

import java.io.*;

....

Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("<your command here>");

See http://java.sun.com/developer/JDCTechTips/2003/tt0304.html

Link to comment
Share on other sites

  • 0
On that note, I actually found out something very interesting. I was recently working on some C code on Windows and decided to parallelize it. Doing some research, I found out that there is no fork() method on Windows. There is only CreateProcess(), which is a combination fork()/exec() which creates a new process without copying the current process's state and instead runs a specified executable. This does impose certain restrictions on what a programmer can do, although the argument could be made that fork() is to expensive that it become unnecessary without exec().

There is no fork() (or spoon()), but Windows has alternative solutions to the same problems. Not only does NT have the concept of a job (which groups processes kind of like processes group threads), but it also has a notion of child processes which inherit environment state from their parents. Further, Windows pretty heavily emphasizes COM, and COM provides out-of-process hosting for COM servers, and even provides a default surrogate host (dllhost.exe) which it will automatically spawn as a child process and even manage the lifetime of those processes for you automatically.

Link to comment
Share on other sites

  • 0

Can anyone provide the ping-pong java thing already compiled so I can try it? I don't feel like getting my Java paths set up just to compile it.

Link to comment
Share on other sites

  • 0
Windows 2000 introduced the NT thread pool as part of the developer API. Mainly this is exposed via the QueueUserWorkItem function. You can read general information about thread pools on MSDN here, or read about the NT thread pool (which was overhauled a bit in Windows Vista) here.

Thanks for the summary. As I mentioned: I'm familiar with the pattern and purpose - I was specifically curious about what Windows offered in terms of kernel level enhancements that say BSD, Linux, or Mac OS X don't. I read over your first link and got the general run-down and I'm afraid I didn't see anything that stood out.

While I agree with there is value of an operating system exposing this functionality with an easy-to-use interface I'm not seeing anything there that strikes me as "secret sauce" material. A quick scan of the API seems to make it easier to configure details and it spares you the nonsense of messing about with (for example) a combination of nstreads and autorelease pool(s) or rolling your own from pthreads, the patterns is so old and universal that I must be missing the part that's unique to windows.

Is the interesting part the fact that Windows ships specific API for creating/using thread pools that spare the developer the annoyance of creating one from scratch or is there more to it that I just can't see?

Is there some sort of unique optimization that Windows kernel does for concurrent tasks implemented using these APIs that aren't done for something like (and I'm pulling this example from my ass) Apache which might opt for cross-platform compatible implementations of the same pattern?

Link to comment
Share on other sites

  • 0
Thanks for the summary. As I mentioned: I'm familiar with the pattern and purpose - I was specifically curious about what Windows offered in terms of kernel level enhancements that say BSD, Linux, or Mac OS X don't. I read over your first link and got the general run-down and I'm afraid I didn't see anything that stood out.

Last I knew, Mac OS didn't have any built-in thread pool before Grand Central (which calls this out as a benefit it is going to offer), so you wouldn't be able to take advantage of having a single watch thread that consolidated supported wait operations across processes, which I believe is one of the advantages of the NT thread pool. That said, this is somewhat outside my field of expertise.

While I agree with there is value of an operating system exposing this functionality with an easy-to-use interface I'm not seeing anything there that strikes me as "secret sauce" material. A quick scan of the API seems to make it easier to configure details and it spares you the nonsense of messing about with (for example) a combination of nstreads and autorelease pool(s) or rolling your own from pthreads, the patterns is so old and universal that I must be missing the part that's unique to windows.

Is the interesting part the fact that Windows ships specific API for creating/using thread pools that spare the developer the annoyance of creating one from scratch or is there more to it that I just can't see?

Is there some sort of unique optimization that Windows kernel does for concurrent tasks implemented using these APIs that aren't done for something like (and I'm pulling this example from my ass) Apache which might opt for cross-platform compatible implementations of the same pattern?

Again, I'm not an expert on that specific functionality, but I've been led to believe that is the case (see above).

In Windows 7 there are some cool new threading features, such as user-mode threads and switch between them with a much less overhead than normal threads handled by the kernel mode scheduler. And on the platform side there is the very cool Concurrency Runtime that makes use of the user-mode scheduler when running on Win7.

Link to comment
Share on other sites

  • 0
There is no fork() (or spoon()), but Windows has alternative solutions to the same problems. Not only does NT have the concept of a job (which groups processes kind of like processes group threads), but it also has a notion of child processes which inherit environment state from their parents. Further, Windows pretty heavily emphasizes COM, and COM provides out-of-process hosting for COM servers, and even provides a default surrogate host (dllhost.exe) which it will automatically spawn as a child process and even manage the lifetime of those processes for you automatically.

But Windows does not provide any implementation of fork()'s functionality, which clones a process AND continues execution of the process at the same location as the fork(). These processes are unrelated, so I don?t believe creating a ?job? would solve this problem. And I?m not sure what you?re saying about COM. As I said, not having a fork() method may a design choice on Microsoft?s part, because if you?re going to use exec() after it, CreateProcess() provides the same functionality. And if you?re not using exec(), you should probably be creating a thread instead of a process anyway.

This is the only example I could think of where Linux has a leg up on Windows as far a parallel programming.

Link to comment
Share on other sites

  • 0
Last I knew, Mac OS didn't have any built-in thread pool before Grand Central (which calls this out as a benefit it is going to offer),

That depends on how you want to slice it. So long as we're just talking about the design pattern - then every OS that supports basic concurrency can make use of thread pools. If you're talking about an API to make it easy to use with desktop applications: then you're absolutely right. The options programmers have at their disposal for concurrency on Mac OS X 10.5 and Linux (keeping in mind I haven't written Linux software in years) leave something to be desired. You can do it, but it's a royal pain in the ass.

That's why things like Grand Central or Windows Thread Pool implementations are so important, the same as other high level APIs like the location services, or the easy-to-use spell checking grammar, thesaurus stuff being built into text widgets.

There isn't a Cocoa carbon equivalent of "[NSTreadPool makeWithThreads:500]" but there'd be nothing stopping you from rolling your own using NSTreads, PThreads, etc. if you're using a C-language. Other languages ship with APIs for thread pools. I vaguely recall TCL having one in University and I believe nearly every modern UNIX-like OS is going to ship with that.

so you wouldn't be able to take advantage of having a single watch thread that consolidated supported wait operations across processes, which I believe is one of the advantages of the NT thread pool.

Are you describing a setup where a thread pool owned by the system (kernel, window server, whatever) and your web servers, games, etc. all pitch their worker threads into that pool?

That'd be an usual setup (from what I've seen in other operating systems) and I'd like to read more about it. I'd have to go back and re-read the API for the queue that you linked but that wasn't the impression I got on my first, admittedly cursory, reading. The marketing fluff for GCD makes it sound like this is sort of how it works, but I haven't read much beyond the technical overview. In apple's case their focus seems to be on making multithreading "stupid easy" in the same way that they tried to make multiple language, or pdf generation stupidly easy.

In Windows 7 there are some cool new threading features, such as user-mode threads and switch between them with a much less overhead than normal threads handled by the kernel mode scheduler.

I remember reading about this - it seemed that on first glance that it was well suited to very tight performance loops. You'd save the obvious context switch and then depending on how light the other work is - possibly a significant number of instructions normally involved in creating/switching threads.

Edited by evn.
Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.