Sobes.tech
Middle

What is the difference between Synchronized and Lock in Java?

sobes.tech AI

Answer from AI

Synchronized is a keyword used to ensure thread safety. It can be applied to methods or code blocks. When entering a synchronized block or method, the thread attempts to acquire the intrinsic lock (monitor of the object). If the lock is held by another thread, the current thread blocks until the lock is released.

Advantages of Synchronized:

  • Simple to use.
  • Automatically releases the lock upon exiting the synchronized block (even in case of exceptions).

Disadvantages of Synchronized:

  • Inflexible: cannot acquire the lock in a non-blocking way, cannot interrupt waiting for the lock, cannot have multiple read locks.
  • Difficult to implement more complex synchronization scenarios, such as lock timeout or unfair lock acquisition order.

Example of Synchronized:

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

Lock is an interface and a set of classes in the java.util.concurrent.locks package, providing more flexible lock management capabilities. The main class is ReentrantLock.

Advantages of Lock:

  • Greater flexibility: can acquire the lock in a non-blocking way (tryLock()), can interrupt lock waiting (lockInterruptibly()), can have different lock types (e.g., ReadWriteLock).
  • Can manage lock fairness (ReentrantLock(boolean fair)).
  • Ability to obtain lock status information (e.g., isLocked()).

Disadvantages of Lock:

  • More complex to use: must explicitly call lock() and unlock(). It is essential to use the finally block to release the lock to avoid deadlocks in case of exceptions.

Example of Lock:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SafeCounter implements Counter {
    private int count = 0;
    private final Lock lock = new ReentrantLock();

    @Override
    public void increment() {
        lock.lock(); // Acquire lock
        try {
            count++;
        } finally {
            lock.unlock(); // Release lock
        }
    }

    @Override
    public int getCount() {
        lock.lock(); // Acquire lock
        try {
            return count;
        } finally {
            lock.unlock(); // Release lock
        }
    }
}

Key differences summarized:

Aspect Synchronized Lock (ReentrantLock)
Type Keyword Interface and classes (API)
Application Methods, code blocks Lock objects
Flexibility Less More
Functions Basic synchronization Non-blocking lock acquisition, interruptible waiting, timeout, different lock types
Releasing Automatic (on exit) Manual (unlock(), usually in finally)
Fairness Cannot be configured (unfair) Can be configured

In general, synchronized is suitable for simple synchronization cases where exclusive access is sufficient. Lock is preferred when greater flexibility and control over the locking process are needed, as well as for implementing more complex parallel access strategies (e.g., using ReadWriteLock).