'What is the use of Condition along with Lock in Java

I am trying to understand what is the use of doing condition.await() if I am already doing lock.lock() If I understood locks correctly, once I do lock.lock() it will not proceed any further if some other thread has a lock.

So, in this case if pushToStack() has acquired a lock by doing lock.lock() then what is the use of checking for stackEmptyCondition.await() in the popFromStack() method? Because anyway, the code will stop at the lock.lock() line in the popFromStack() method. What am I missing/wrong?

public class ReentrantLockWithCondition {

    Stack<String> stack = new Stack<>();
    int CAPACITY = 5;

    ReentrantLock lock = new ReentrantLock();
    Condition stackEmptyCondition = lock.newCondition();
    Condition stackFullCondition = lock.newCondition();

    public void pushToStack(String item){
        try {
            lock.lock();
            while(stack.size() == CAPACITY) {
                stackFullCondition.await();
            }
            stack.push(item);
            stackEmptyCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public String popFromStack() {
        try {
            lock.lock(); // we are blocked here to acquire a lock
            while(stack.size() == 0) {
                stackEmptyCondition.await(); // then why do we need to check this again?
            }
            return stack.pop();
        } finally {
            stackFullCondition.signalAll();
            lock.unlock();
        }
    }
}


Solution 1:[1]

The point is the Condition, not the Lock.

It is often the case that a program needs to wait until either "something happens" or "something is in a particular state". The Condition represents what you're waiting for.

In order to program such a thing safely, some sort of locking is needed. If you're waiting for something to be in a particular state, you really want it to remain in that state while you do whatever you had in mind when you decided to wait for it. That's where the Lock comes in.

In your example, you want to wait until the stack is not full, and when you discover that the stack is not full, you want it to stay not-full (that is, prevent some other thread from pushing on to the stack) while you push something on that stack.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dangling else