Enhancing Java Concurrency: Processor, Core, Threads, Fibers
Tags: java, programming, beginners
Published: 2024-02-16 17:03:08

Regardless of your experience as a Java developer, you've likely encountered threads in your work and have come across terms like **_processor_**, **_core_** and **_fiber_**. However, you might not fully understand the distinctions among them or their specific roles in Java's concurrency model. In this blog, I aim to demystify these concepts, explaining their unique meanings and functions within the framework of application execution. Grasping these differences is crucial for comprehending the fundamentals of concurrent and parallel computing

- **Processor:**
The processor, or Central Processing Unit (CPU), is the primary hardware component in a computer that executes instructions from software. It performs the basic arithmetical, logical, and input/output operations of the system.

- **Core:**
A core is an individual processing unit within a processor. Early CPUs had only one core, meaning they could only execute one sequence of instructions at a time. Modern CPUs, however, can have multiple cores, allowing them to execute multiple instruction sequences simultaneously. Each core can independently run one or more threads, making multi-core processors well-suited for multitasking and parallel processing.

- **Thread**
In Java, a thread represents a single sequence of executed instructions within a program. It is the smallest unit of execution that the Java Virtual Machine (JVM) can schedule and manage. Java allows programs to execute multiple threads concurrently, using the _Thread_ class or the _Runnable_ interface. Threads within the same process share the process's memory and resources but can be executed in parallel across multiple cores of a CPU to improve performance.
- **Fiber** 
Fibers are lightweight threads designed to further enhance concurrency. Unlike traditional threads, which are managed by the operating system and have a significant context-switching overhead, fibers are managed by the JVM and are designed to have much lower overhead. This allows applications to spawn thousands or even millions of fibers, enabling massive concurrency. Fibers aim to simplify concurrent programming in Java by providing a model where developers can write code as if it were sequential, but execute it concurrently.

**Example with image to explain more:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbq1zk2v6nudnfmpwqa6.JPG)

The image provided appears to illustrate a dual-core CPU, with each core running two threads and each core having its own set of caches (L1 instruction cache, L1 data cache, and a shared L2 cache), as well as sharing a common L3 cache that, in turn, interfaces with the main memory. Here’s how this relates to Java and CPU processors

**- CPU Cores and Threads in Java:**
In a Java application, when you create threads using the Thread class or by implementing the Runnable interface, the Java Virtual Machine (JVM) maps these threads onto the available CPU cores for execution.

**Core 0 and Core 1:** These represent individual processing units within the CPU. Modern CPUs can have multiple cores, allowing them to execute multiple threads in parallel.
**Thread 0 and Thread 1:** On each core, we see two threads, which could be Java threads. The operating system's scheduler determines which thread runs on which core and when. If a core is executing Thread 0, and it gets switched out for Thread 1, this is a context switch, which is a low-level task handled by the operating system to manage CPU time between multiple tasks.
**Caches (L1, L2, and L3)**: Caches are fast, small memories located close to or inside the CPU that store frequently accessed data to speed up access times. The L1 cache is split into an instruction cache and a data cache for storing instructions and data separately. The L2 cache is usually shared between the L1 caches of different cores (although it can also be core-specific), and the L3 cache is shared across all cores, interfacing between the CPU and the main memory. When a Java thread requires data, it first checks the cache before going to the main memory, which is slower.

Understanding this architecture is crucial for Java developers, especially when building applications that require high levels of concurrency and need to be optimized for performance. The way Java threads utilize CPU cores and caches can significantly affect application throughput, latency, and scalability.