Answer to Question 4 -- 10 points

  1. In a non-threaded uniprocessor system, asynchronous operations allow user processes to perform I/O in a non-blocking fashion. In other words it allows them to overlap I/O with computation. For example, you can write a data structure to disk, and while doing that, perform some computation on other data structures. True, you can effect this by calling fork() and having the child write the data structure, but asynchronous operations have much, much less overhead.

  2. If you are in a threaded uniprocessor system, you don't need asynchronous operations, since you can fork a thread to perform the operation synchronously, while other threads work on the CPU. This is much more desirable than using asynchronous operations because you don't have to worry about when to test to see if the operation has completed. Moreover, you can use standard synchronization operations (e.g. semaphores or monitors/cv's) to protect the data structures involved while the operation is going on. The programming model is extremely elegant and much easier to use than asynchronous operations.

    It really does not matter if the thread system is preemptive or non-preemptive, because it doesn't matter if threads get interrupted in mid-stream or if multiple threads can get work done at the same time. What matters is that threads can run while a thread is blocked on a synchronous, blocking system call. If they can't (as in SunOS threads), then you need asynchronous operations for efficiency.