The operating system must do extra work to manage multitasking. Programmers call this extra work overhead because resources inside your computer are used to manage the multitasking operation rather than being used by programs for processing instructions and data.
Process-based multitasking has a larger overhead than thread-based multitasking. In process-based multitasking, each process requires its own address space in memory. The operating system requires a significant amount of CPU time to switch from one process to another process. Programmers call this context switching, where each process (program) is a context. Additional resources are needed for each process to communicate with each other.
In comparison, the threads in thread-based multitasking share the same address space in memory because they share the same program. This also has an impact on context switching, because switching from one part of the program to another happens within the same address space in memory. Likewise, communication among parts of the program happens within the same memory location.
Threads
A thread is part of a program that is running. Thread-based multitasking has multiple threads running at the same time (that is, multiple parts of a program running concurrently). Each thread is a different path of execution.
Let’s return to the word processing program example to see how threads are used. Two parts of the word processor are of interest: The first is the part of the program that receives characters from the keyboard, saves them in memory, and displays them on the screen. The second part is the portion of the program that checks spelling. Each part is a thread that executes independently of each other, even though they are part of the same program. While one thread receives and processes characters entered into the keyboard, the other thread sleeps. That is, the other thread pauses until the CPU is idle. The CPU is normally idle between keystrokes. It is this time period when the spell checker thread awakens and continues to check the spelling of the document. The spell checker thread once again pauses when the next character is entered into the keyboard.
The Java run-time environment manages threads, unlike in process-based multitasking where the operating system manages switching between programs. Threads are processed asynchronously. This means that one thread can pause while other threads continue to process.
A thread can be in one of four states:
All threads are not equal. Some threads are more important than other threads and are giving higher priority to resources such as the CPU. Each thread is assigned a thread priority that is used to determine when to switch from one executing thread to another. This is called context switching.
A thread’s priority is relative to the priority of other threads. That is, a thread’s priority is irrelevant if it is the only thread that is running. A lower-priority thread runs just as fast as a higher-priority thread if no other threads are executing concurrently.
Thread priorities are used when the rules of context switching are being applied. These rules are as follows:
Synchronization Multithreading occurs asynchronously, meaning one thread executes independently of the other threads. In this way, threads don’t depend on each other’s execution. In contrast, processes that run synchronously depend on each other. That is, one process waits until the other process terminates before it can execute.
Sometimes the execution of a thread is dependent on the execution of another thread. Let’s say you have two threads—one handles gathering login information, and the other validates a user’s ID and password. The login thread must wait for the validation thread to complete processing before it can tell the user whether or not the login is successful. Therefore, both threads must execute synchronously, not asynchronously.
Java enables you to synchronize threads by defining a synchronized method. A thread that is inside a synchronized method prevents any other thread from calling another synchronized method on the same object. You’ll learn how to do this later in the chapter.