Shared Model-Immutability

Immutability Design

Immutability is a design principle where classes and their attributes are marked as final, ensuring that the attributes are read-only and cannot be modified.

Protective Copy

Protective copying involves creating copy objects to prevent sharing. This technique safeguards the content of arrays from being altered by other classes.

Flyweight Pattern

The Flyweight pattern emphasizes data sharing to minimize resource wastage. Instead of using protective copying, it aims to wrap frequently used data in shared objects.

Thread Safety: Java Memory Model (JMM)

Java Memory Model (JMM)

JMM defines main memory and working memory concepts, which correspond to CPU registers, caches, hardware memory, and CPU instruction optimizations. It ensures thread safety through concepts like atomicity, visibility, and ordering.

Atomicity

Atomicity guarantees that instructions are not influenced by thread context switches.

Visibility

Visibility ensures that instructions are not affected by CPU caching. You can use volatile to address visibility issues, making variables read directly from main memory.

Ordering

Ordering ensures that instructions are not affected by CPU instruction parallelization. To prevent instruction reordering, volatile can be used.

Thread Safety: Shared Models and Strategies

Shared Models

  • Double-Checked Locking: Lazy instantiation with potential issues. Adding volatile to the instance variable can resolve ordering problems.
  • Happens-Before: Rules that govern shared variable writes and reads, ensuring visibility and ordering.
  • Read-Write Locks: Use cases for ReentrantReadWriteLock to enhance read concurrency while ensuring write exclusivity.

Thread Pools

ThreadPoolExecutor

ThreadPoolExecutor manages thread pools with states represented by an atomic variable (ctl) combining thread pool status and the number of threads.

ThreadPool Types

  • newFixedThreadPool: Core and maximum threads are equal, suitable for tasks with known quantities.
  • newCachedThreadPool: Core threads are 0, and maximum threads are Integer.MAX_VALUE, useful for tasks with short execution times.
  • newSingleThreadExecutor: Sequential execution with a single thread.
  • Custom Sizing: Adjust thread pool size based on CPU characteristics (e.g., CPU-bound vs. I/O-bound tasks).

Synchronization and Locking

AQS and ReentrantLock

AbstractQueuedSynchronizer (AQS) forms the basis for various synchronization primitives like ReentrantLock.

ReentrantLock Principles

  • Non-fair locking implementation.
  • Reentrant and interruptible locking modes.
  • Supports condition variables.
  • Shared implementation for read and write locks.

StampedLock

StampedLock, introduced in JDK 8, enhances read performance and supports optimistic reads. It uses “stamps” for synchronization.

Semaphore

Semaphores limit concurrent access to shared resources by controlling the number of threads allowed.

CountdownLatch and CyclicBarrier

CountdownLatch

CountdownLatch is used for thread synchronization, allowing threads to wait until a specified count reaches zero.

CyclicBarrier

CyclicBarrier coordinates threads by waiting for a specific number of threads to reach a barrier point before proceeding.

These concepts and strategies are essential for understanding thread safety and efficient concurrent programming in Java.