You could mail me or go to my home page, or the main squirrelly page.
When designing a system with more processes than processors, one has to consider how to share these processors. The two most popular methods are cooperative, in which each process will voluntarily relinquish the processor when convenient, and preemptive, in which the processor is taken from the process at what seem to the process to be arbitrary intervals.
There are also two ways to have different processes. There is the standard multiprocess model and the thread model. The difference, in general, is whether they have their own memory segment, or whether they share. Threads are sometimes called "lightweight processes".
For different applications, the "heavyweight process" model makes sense. You don't want one application mucking with another application's memory space (although it does happen in systems without hardware memory management). Similarly, it is unwise for one application to trust other applications, as some will be badly written. This is particularly true for developers, who are going to run badly-written applications to test and debug them. No application should be able to do more than crash itself. Therefore, heavyweight processes should use preemptive scheduling, although the Macintosh model of cooperative scheduling among separate apps has worked well.
Now, let's consider threads. If two processes are going to share memory, they will have to trust each other. Therefore, there's no need for preemptive multitasking, as one thread can certainly crash all threads it is associated with. The question is, therefore, whether cooperative or preemptive is better for the programmer. The answer is that cooperative is generally better. It simplifies programming and makes it easier to find bugs.
Threads generally interact by changing shared memory. Now, it is very useful to be able to know that one's memory is in a consistent and reliable state. However, while changing some structure in memory, it is unlikely to be in such a state during the change. We therefore have to find some way of allowing threads to monopolize data structures for a short while. This is generally done, in preemptive threads, by making some sort of request for exclusive access, and by having all threads ask for exclusive access when they need to access that data, and relinquish it when through. This is frequently cumbersome, and often easy to forget or get wrong. When this happens, the program has a timing bug that may show up essentially at random, and these are very hard to find. In cooperative threads, each thread is responsible for specifying when it's willing to yield to another thread. It is fairly easy to make sure all data structures are in a good state when specifying this. Further, if there are not enough of these yield calls, this will become quickly apparent in testing.
Therefore, there are two answers. Standard processes should be preemptively scheduled, and should have hardware memory protection. Threads should be cooperatively scheduled.
If you want my opinion, just ask.
If you don't want my opinion, flee.
All contents of these pages Copyright 1997 by David H. Thornley.