← Back to Multithreading Course

Class 16: Instance Locks and Class Locks

Understand the difference between object-level locks and class-level locks in Java.

1. A Quick Recap

In our previous classes, we learned that every Java object has an associated monitor lock.

When a thread enters a synchronized instance method, it acquires the lock associated with that particular object.

For example:

class Counter {

    int count = 0;

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

Here, the synchronized method uses the lock of the current Counter object.

Let's understand what happens when we create multiple objects of the same class.

2. Understanding Instance Locks

Consider the following code:

Counter counter1 = new Counter();
Counter counter2 = new Counter();

We have created two different Counter objects.

Each object has its own instance lock.

This means that a thread executing a synchronized instance method on counter1 does not prevent another thread from executing a synchronized instance method on counter2.

Why?

Because they are using two different objects, and therefore two different locks.

Let's look at a complete example.

class Counter {

    synchronized void printMessage() {
        System.out.println(
            "Executing: " + Thread.currentThread().getName()
        );
    }
}

public class Main {

    public static void main(String[] args) {

        Counter counter1 = new Counter();
        Counter counter2 = new Counter();

        Thread t1 = new Thread(
            () -> counter1.printMessage()
        );

        Thread t2 = new Thread(
            () -> counter2.printMessage()
        );

        t1.start();
        t2.start();
    }
}

Both threads can execute the synchronized method without waiting for each other because they use different Counter objects.

Remember: an instance lock belongs to an individual object, not to the class as a whole.

3. What Is a Class Lock?

So far, we have discussed locks associated with individual objects.

But Java also allows us to synchronize access at the class level.

We do this using a static synchronized method.

class Counter {

    static synchronized void printMessage() {
        System.out.println("Hello from a static method");
    }
}

Notice the combination of two keywords:

  • static means the method belongs to the class.
  • synchronized means the method requires a lock before execution.

A static synchronized method uses the lock associated with the class itself.

This is commonly called the class lock.

For example, the class lock for Counter is represented by:

Counter.class

You can think of Counter.class as the Class object representing the Counter class.

4. Understanding a Class Lock with Two Objects

Let's create two Counter objects again.

class Counter {

    static synchronized void printMessage() {

        System.out.println(
            "Executing: " + Thread.currentThread().getName()
        );
    }
}

public class Main {

    public static void main(String[] args) {

        Counter counter1 = new Counter();
        Counter counter2 = new Counter();

        Thread t1 = new Thread(
            () -> counter1.printMessage()
        );

        Thread t2 = new Thread(
            () -> counter2.printMessage()
        );

        t1.start();
        t2.start();
    }
}

Notice something interesting.

Even though we have two different Counter objects, both threads are calling the same static synchronized method belonging to the Counter class.

Both calls require the same class lock.

Therefore, only one thread at a time can execute this static synchronized method.

The class lock is shared by all objects of that class.

5. Instance Lock vs. Class Lock

Let's put both types of locks side by side.

Instance Lock Class Lock
Associated with an individual object. Associated with the class.
Used by synchronized instance methods. Used by static synchronized methods.
Different objects have different instance locks. All objects of the same class use the same class lock.
Can be represented by this inside an instance method. Can be represented by Counter.class.

6. Do Instance Locks and Class Locks Block Each Other?

This is an important question.

Consider this class:

class Counter {

    synchronized void instanceMethod() {
        System.out.println("Instance method");
    }

    static synchronized void classMethod() {
        System.out.println("Static method");
    }
}

The instance method uses the lock of a particular Counter object.

The static synchronized method uses the Counter class lock.

These are two different locks.

Therefore, a thread executing instanceMethod() does not automatically block another thread executing classMethod().

Both methods can execute at the same time, provided no other synchronization is involved.

7. A synchronized Static Block

Just as we can use synchronized blocks with instance locks, we can also use synchronized blocks with the class lock.

We can write:

class Counter {

    static int count = 0;

    static void increment() {

        synchronized (Counter.class) {
            count++;
        }
    }
}

Here, Counter.class is used as the lock object.

This block uses the same class lock as a static synchronized method in the Counter class.

This is useful when we want to protect access to shared static data.

8. A Few Things to Remember

  • Every object has its own instance lock.
  • A synchronized instance method uses the current object's lock.
  • A static synchronized method uses the class lock.
  • All objects of the same class share that class lock.
  • Counter.class represents the Class object used as the class lock.
  • Instance locks and class locks are different locks.
  • A synchronized block using Counter.class uses the same class lock as a static synchronized method of Counter.

Remember: Instance synchronization protects access using an individual object's lock. Static synchronization protects access using the class lock.

Test Your Understanding

Let's see how well you understood this class!

Question 1: What lock does a synchronized instance method use?

Question 2: What lock does a static synchronized method use?

Question 3: Two different Counter objects call the same synchronized instance method. Do they use the same instance lock?

Question 4: What does Counter.class represent in a synchronized block?

Question 5: Do an instance synchronized method and a static synchronized method of the same class use the same lock?

Class Summary

Let's quickly revise what we learned in this class.

  • Every Java object has its own instance lock.
  • A synchronized instance method uses the current object's lock.
  • A static synchronized method uses the class lock.
  • All objects of the same class share the same class lock.
  • Counter.class can be used as the class lock in a synchronized block.
  • Instance locks and class locks are separate from each other.

Remember: Instance locks belong to objects, while class locks belong to classes.

What's Next?

Class 17: The volatile Keyword

We have learned how synchronization helps protect shared data by controlling which thread can access it.

But what if one thread changes a shared variable and another thread does not immediately see that change?

In the next class, we will learn about the volatile keyword and how it helps threads see the latest value of a shared variable.

See you in the next class!

0% Completed

You have completed 16 out of 46 classes.