The LWPs are part of the process structure, but we show them crossing the line because this is
how we think of their use. They are the main vehicle for processing from the threads library's
point of view, so we show them in illustrations crossing that boundary, although they are, strictly
speaking, in kernel space. The actual process structure is completely in kernel space.
As you can deduce, this definition of threads residing in a single address space means that the
entire address space is seen identically by all threads. A change in shared data by one thread can
be seen by all the other threads in the process. If one thread is writing a data structure while
another thread is reading it, there will be problems (see Race Conditions ).
As threads share the same process structure, they also share most of the operating system state.
Each thread sees the same open files, the same user ID, the same working directory; each uses the
same file descriptors, including the file position pointer. If one thread opens a file, another thread
can read it. If one thread does a seek() while another thread is doing a series of reads on the
same file descriptor, the results may be surprising.
All of this is true no matter if you think of the running code as being native or as residing inside
the JVM; the issues and consequences are the same. In some fashion, the JVM uses a threads
library (possibly a native library such as POSIX or Win32, possibly its own library, green threads)
to provide the infrastructure for your threads to run on. As far as you can tell, you're just running
Java threads, but underneath you're running on the lower-level library (Figure 3-4).
Figure 3-4. How Java Is Built on Lower-Level Threads Libraries
Search WWH :