Java threading introduction  Thread-safety  Thread methods  Interruption  Thread scheduling  Context switching  Thread priorities  sleep()  yield()  Deadlock  Threading with Swing  invokeLater()  Thread pools  CoundDownLatch  ThreadPoolExecutor  CyclicBarrier

How threads work: more details

In our introduction to Java threads, we showed the basics of how to start a thread, and the idea that threads let us run multiple tasks or "mini-programs" in parallel. But to understand certain thread programming issues in more detail, it's helpful to take a more detailed look at what threads actually are and how they work.

Figure 1: Typical relationsip between
threads and processes

Threads and processes

A thread is essentially a subdivision of a process, or "lightweight process" (LWP) on some systems. A process is generally the most major and separate unit of execution recognised by the OS. The typical relationship between processes, threads and various other elements of the OS are shown in Figure 1 opposite. This shows two processes, each split into two threads (a simplistic situation, of course: there will be typically dozens of processes, some with dozens or more threads).

Crucially, each process has its own memory space. When Process 1 accesses some given memory location, say 0x8000, that address will be mapped to some physical memory address1. But from Process 2, location 0x8000 will generally refer to a completely different portion of physical memory. A thread is a subdivision that shares the memory space of its parent process. So when either Thread 1 or Thread 2 of Process 1 accesses "memory address 0x8000", they will be referring to the same physical address. Threads belonging to a process usually share a few other key resources as well, such as their working directory, environment variables, file handles etc.

On the other hand, each thread has its own private stack and registers, including program counter. These are essentially the things that threads need in order to be independent. Depending on the OS, threads may have some other private resources too, such as thread-local storage (effectively, a way of referring to "variable number X", where each thread has its own private value of X). The OS will generally attach a bit of "housekeeping" information to each thread, such as its priority and state (running, waiting for I/O etc).

The thread scheduler

There are generally more threads than CPUs. Part of a multithreaded system is therefore a thread scheduler, responsible for sharing out the available CPUs in some way among the competing threads. Note that in practically all modern operating systems, the thread scheduler is part of the OS itself. So the OS actually "sees" our different threads and is responsible for the task of switching between them2. The rationale for handling threading "natively" in the OS is that the OS is likely to have the information to make threading efficient (such as knowing which threads are waiting for I/O and for how long), whereas a software library may not have this information available. In the rest of our discussion, we'll generally assume this native threads model.

Next: scheduling and its implications for Java

On the next pages, we look at

1. Things are usually a little more complex, in fact. For example, a memory address can actually be mapped to something that isn't memory (such as a portion of a file, or device I/O). For this reason, the term address space is often preferred.
2. An alternative scenario, less common nowadays, is that the OS schedules at some higher level, e.g. scheduling processes, or scheduling some kind of "kernal thread" which is a unit bigger than our applications threads. In this model, sometimes called "green threads", threads are to some extent "artificially" handled by the JVM (or the threading library that it is compiled against). In general, if you are using Java 1.4 onwards on Windows or on Solaris 9 or Linux kernel 2.6 or later, then there will be a 1:1 mapping between Java Threads and "native" operating system threads.

 Java threading articles  Java threading and concurrency  Java profiling  Java performance graph index

Unless otherwise stated, the Java programming articles and tutorials on this site are written by Neil Coffey. Suggestions are always welcome if you wish to suggest topics for Java tutorials or programming articles, or if you simply have a programming question that you would like to see answered on this site. Most topics will be considered. But in particular, the site aims to provide tutorials and information on topics that aren't well covered elsewhere, or on Java performance information that is poorly described or understood. Suggestions may be made via the Javamex blog (see the site's front page for details).
Copyright © Javamex UK 2016. All rights reserved.