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.