Fundamentals 22 min read

Java Lock Types and Their Implementation Details

This article provides a comprehensive overview of various Java lock mechanisms—including fair, non‑fair, reentrant, read/write, biased, lightweight, heavyweight, and spin locks—explaining their classifications, usage, underlying AQS implementation, and includes illustrative code snippets for each type.

Big Data Technology & Architecture
Big Data Technology & Architecture
Big Data Technology & Architecture
Java Lock Types and Their Implementation Details

The article gathers and organizes publicly available resources on Java concurrency locks, acknowledging contributors and recommending JDK 1.8+ source code for reference.

1. Classification of Java Locks

The article lists common lock categories such as fair vs. non‑fair locks, reentrant locks, exclusive vs. shared locks, mutex vs. read‑write locks, optimistic vs. pessimistic locks, segment locks, biased/lightweight/heavyweight locks, and spin locks, and briefly explains the meaning of each term.

2. Fair and Non‑Fair Locks

Fair locks grant access in FIFO order, while non‑fair locks may allow a thread that just released the lock to reacquire it, improving throughput at the cost of possible thread starvation.

public ReentrantLock() {
    sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

The non‑fair acquisition simply tries to set the state, whereas the fair version checks hasQueuedPredecessors() before proceeding.

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    } else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

3. ReentrantLock Reentrancy

Reentrancy is achieved by allowing the same thread to acquire the lock multiple times, incrementing an internal hold count. Release occurs only when the count reaches zero.

final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    } else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

4. Lock Interface

Since JDK 1.5, the Lock interface and its implementations (e.g., ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock) provide more flexible locking than the built‑in synchronized keyword.

5. AbstractQueuedSynchronizer (AQS)

AQS supplies the core framework for building both exclusive (mutex) and shared (read‑write) synchronizers. Implementations override methods such as tryAcquire, tryRelease, tryAcquireShared, and tryReleaseShared to define lock semantics.

6. ReentrantReadWriteLock

The write lock is exclusive and follows the same reentrancy rules as ReentrantLock. The read lock is shared, allowing multiple readers simultaneously as long as no writer holds the lock.

protected final boolean tryAcquire(int acquires) {
    Thread current = Thread.currentThread();
    int c = getState();
    if (c != 0) {
        int w = exclusiveCount(c);
        if (w == 0 || current != getExclusiveOwnerThread())
            return false;
        // reentrant acquire
        int nextc = c + acquires;
        if (nextc < 0) throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    if (writerShouldBlock() || !compareAndSetState(c, c + acquires))
        return false;
    setExclusiveOwnerThread(current);
    return true;
}
protected final int tryAcquireShared(int unused) {
    Thread current = Thread.currentThread();
    int c = getState();
    if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current)
        return -1;
    int r = sharedCount(c);
    if (!readerShouldBlock() && r < MAX_COUNT && compareAndSetState(c, c + SHARED_UNIT)) {
        // record first reader, hold counts, etc.
        return 1;
    }
    return fullTryAcquireShared(current);
}

Read‑lock release decrements the shared count (high 16 bits of the state) and may allow waiting writers to proceed.

protected final boolean tryReleaseShared(int unused) {
    Thread current = Thread.currentThread();
    // update firstReader or HoldCounter as needed
    for (;;) {
        int c = getState();
        int nextc = c - SHARED_UNIT;
        if (compareAndSetState(c, nextc))
            return nextc == 0;
    }
}

7. Lock Downgrade

Read‑write locks support downgrading: a thread can acquire the write lock, then the read lock, and finally release the write lock, keeping read access without ever upgrading from read to write.

void processCachedData() {
    rwl.readLock().lock();
    if (!cacheValid) {
        rwl.readLock().unlock();
        rwl.writeLock().lock();
        try {
            if (!cacheValid) {
                data = ...;
                cacheValid = true;
            }
        } finally {
            rwl.writeLock().unlock();
        }
        rwl.readLock().lock(); // downgrade
    }
    try {
        use(data);
    } finally {
        rwl.readLock().unlock();
    }
}

8. References

Books: "Java Concurrency in Practice" and "Effective Java High‑Concurrency Programming"; online articles from CSDN and Jianshu are cited for further reading.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencymultithreadingLocksAQSReentrantLockReadWriteLock
Big Data Technology & Architecture
Written by

Big Data Technology & Architecture

Wang Zhiwu, a big data expert, dedicated to sharing big data technology.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.