Processes and Threads
Processes and Threads
Processes
A process is responsible for loading instructions, managing memory, and handling I/O operations. Think of a process as an instance of a program; while programs are static, processes are dynamic. When a program is executed, it initiates a process.
Processes are independent entities, and multiple processes can run concurrently on a system. They have their own memory spaces, resources, and execution environments.
Processes have shared resources, such as memory space, among their internal threads.
Inter-process communication (IPC) is the mechanism for processes to communicate on the same machine, while communication between processes on different machines often relies on network protocols like HTTP.
Threads
Threads are smaller units of execution within a process. A process can consist of one or more threads, and threads within the same process share the process’s resources.
In Java, threads are the smallest scheduling units for executing instructions, and processes serve as resource management units. In Windows, processes act as containers for threads, but the process itself is not active.
Threads enable concurrent execution within a single process, allowing multiple instruction streams to be scheduled and executed by the CPU.
Parallelism and Concurrency
Parallelism
Parallelism refers to the ability to perform multiple tasks at the same time on a multi-core CPU. It involves true simultaneous execution of instructions.
Concurrency
Concurrency, on the other hand, involves managing multiple tasks in overlapping time periods, where threads take turns executing, even on a single-core CPU. It’s achieved through task scheduling.
Asynchronous vs. Synchronous
Synchronous
In synchronous method calls, the program waits for the result before continuing execution.
Asynchronous
Asynchronous method calls don’t require waiting for results before proceeding. They allow the program to continue execution while the called task is performed in the background.
Multithreading can make method execution asynchronous, enhancing efficiency, especially on multi-core CPUs.
Java Threads
Creating Threads
Java provides mechanisms to create and manage threads. Threads in Java can be created by extending the Thread class or implementing the Runnable interface.
Viewing Processes and Threads
To manage processes and threads in various environments, you can use tools like Task Manager (Windows), ps and kill commands (Linux), or Java-specific utilities like jps and jstack.
Thread States
Threads in Java can be in various states, including:
- NEW: Created but not started.
- RUNNABLE: Eligible for execution.
- RUNNING: Currently executing.
- BLOCKED, WAITING, TIMED_WAITING: Blocked or waiting for certain conditions.
- TERMINATED: Execution completed.
Shared Models
Concurrent programs often involve shared resources and critical sections.
- Critical Section: A portion of code in which multiple threads access shared resources, leading to potential race conditions.
To avoid race conditions, you can use blocking (synchronized, locks) or non-blocking (atomic variables) techniques.
Synchronized Blocks
Synchronized blocks in Java help protect critical sections of code by allowing only one thread at a time to execute the synchronized block of code. You can synchronize on an object, a method, or a class.
Synchronized blocks ensure the atomicity of code within the block, preventing race conditions and guaranteeing exclusive access to shared resources.
Thread Safety
Certain classes in Java are inherently thread-safe because they’re designed to be used safely in a multithreaded environment. Examples include:
- String
- Integer
- StringBuffer
- Random
- Vector
- Hashtable
- Classes from the java.util.concurrent package
These classes are thread-safe when multiple threads call their methods on the same instance simultaneously. However, combining methods of these classes might not always result in thread-safe operations.
String and Integer are examples of immutable classes, making their methods inherently thread-safe because they don’t modify internal state.
Keep in mind thread safety when working with shared variables, as thread synchronization may be necessary to ensure proper operation in a multi-threaded environment.