askvity

What is synchronized in Java?

Published in Java Thread Synchronization 4 mins read

In Java, synchronized is a keyword used to achieve thread safety. It ensures that only one thread can execute a specific block of code or method at any given time, preventing data corruption in multi-threaded environments.

Understanding Synchronization in Java

When multiple threads access shared resources concurrently, problems like race conditions can occur. A race condition happens when the outcome of a program depends on the unpredictable order in which threads execute.

Based on the provided reference:

Synchronization in Java is the process that allows only one thread at a particular time to complete a given task entirely. By default, the JVM gives control to all the threads present in the system to access the shared resource, due to which the system approaches race condition.

This highlights the core purpose of synchronized: to control access to shared resources and prevent race conditions by enforcing serial execution for critical sections of code.

How synchronized Works

The synchronized keyword can be applied to:

  1. Methods: When a method is declared synchronized, the entire method body becomes a critical section. For instance-level methods, threads must acquire the monitor (or intrinsic lock) of the object instance before executing the method. For static methods, threads must acquire the monitor of the Class object.

    public class Counter {
        private int count = 0;
    
        public synchronized void increment() {
            count++; // This operation is now thread-safe
        }
    
        public int getCount() {
            return count;
        }
    }
  2. Blocks: You can synchronize a specific block of code within a method by using synchronized(object) { ... }. The object inside the parentheses is the monitor (lock) that threads must acquire before entering the block. This allows for finer-grained control than synchronizing an entire method.

    public class DataProcessor {
        private final List<String> data = new ArrayList<>();
        private final Object lock = new Object(); // A dedicated lock object
    
        public void addData(String item) {
            // Only synchronize the code that modifies the shared resource
            synchronized (lock) {
                data.add(item);
            }
            // Other non-critical operations can happen outside the block
        }
    
        // Example using the object's intrinsic lock
        public void process() {
             synchronized (this) {
                // Access/modify instance state safely
             }
        }
    }

When a thread acquires the monitor associated with a synchronized method or block, no other thread can acquire the same monitor until the first thread releases it (usually when it exits the synchronized area). This ensures that only one thread is accessing the protected resource at any given moment.

Why Use Synchronization?

  • Preventing Race Conditions: The primary reason is to avoid unpredictable behavior and data corruption when multiple threads interact with shared data.
  • Maintaining Data Consistency: Ensures that operations on shared data are completed atomically (as a single, uninterruptible unit) from the perspective of other threads.
  • Thread Safety: Makes classes and methods safe to use in multi-threaded applications.
Benefit of Synchronization Explanation
Thread Safety Guarantees correct behavior in concurrent environments.
Data Consistency Ensures shared data remains in a valid state.
Atomicity Makes operations on shared resources appear as single actions.
Preventing Race Conditions Avoids errors resulting from unpredictable thread execution order.

Considerations

  • Performance Overhead: Synchronization adds overhead due to lock acquisition and release. Overuse can lead to reduced performance.
  • Deadlocks: Incorrectly implemented synchronization can lead to deadlocks, where two or more threads are blocked indefinitely waiting for each other to release locks.
  • Scope: Carefully choose whether to synchronize entire methods or just specific blocks to minimize the critical section and improve concurrency where possible.

In summary, synchronized in Java is a fundamental mechanism based on monitors (intrinsic locks) provided by the JVM to enforce mutual exclusion, ensuring that concurrent access to shared resources is controlled, thus preventing race conditions and maintaining data integrity.

Related Articles