All of the OSs discussed here were designed to run on uniprocessor systems and tightly coupled,
shared memory multiprocessors. The kernel assumes that all processors are equivalent. Processors
run kernel threads from the queue of runnable kernel threads (just as in user code). If a particular
multiprocessor implementation places an asymmetric load on the processors (e.g., if interrupts are
all directed to a single CPU), the kernel will nonetheless schedule threads to processors as if they
were equivalent, not taking this asymmetry into account.
Are Libraries Safe?
Just because you write perfectly safe code that will run in a multithreaded environment with no
problems doesn't mean that everyone else can. What would happen if you wrote a wonderful MT
program, but then called a library routine that used a bunch of global data and didn't lock it? You'd
lose. So you must be certain that if you call a routine from multiple threads, it's MT-safe, which
means that a function must lock any shared data it uses and it in turn must only call other MT-safe
Well, even programmers with the best of intentions find themselves with conflicting goals. "Make
it fast" and "Make it MT-safe" don't always agree. Some routines in some libraries will not be
MT-safe. It's a fact of life, and you have to deal with it. The documentation for each library call
should indicate its level of "MT safeness." It is often quite unclear from the Java spec just which
methods are or are not thread-safe.
Libraries and classes themselves are not safe or unsafe, per se. The methods in them are (or aren't).
Just to confuse things, there are libraries that contain some methods that are safe and some
methods that aren't safe. Every time you use a method, you must make sure that it's MT-safe.
The calls read() and write() are technically MT-safe, inasmuch as you can call them from
multiple threads and get correct results. Unfortunately, they both move a pointer associated with
the file descriptor. In practice, if you perform concurrent operations from different threads on the
same file descriptor, you're likely to get very confused. For this reason, in UNIX98 there is a pair
of calls (Figure 11-2): pread() and pwrite(), which operate exactly the same way as read()
and write(), except that you have to pass an explicit file position pointer along with them.
Figure 11-2. Using pread() and pwrite() to Keep Track of the File Pointer
No such calls exist in Java, so you are forced to open file descriptors for a file if that is the
what we do.]
Search WWH :