Class level lock is a lock on the Class object, used when working with static synchronized methods or blocks. Only one thread can execute any static synchronized code of a class at a time, regardless of number of objects.
It is mainly used to protect shared static data.
- Lock is applied on the class, not on objects (common for all instances).
- Achieved using static synchronized methods or synchronized(ClassName.class) block.
- Ensures only one thread executes static synchronized code at a time.
Methods of Class Level Lock
1. Using the synchronized static method
This method automatically acquires the class-level lock when a thread enters it. Only one thread can execute any static synchronized method of the class at a time.
- Lock is on ClassName.class
- Applied directly using static synchronized
- Simple and automatic locking
class Geek implements Runnable {
// Method 1
// @Override
public void run() { Lock(); }
// Method 2
// Method is static
public static synchronized void Lock()
{
// Gwetting the name of current thread by using
// getName() method to get name of the thread and
// currentThread() to get the current thread
System.out.println(
Thread.currentThread().getName());
// class level lock
synchronized (Geek.class)
{
System.out.println(
"in block "
+ Thread.currentThread().getName());
System.out.println(
"in block "
+ Thread.currentThread().getName()
+ " end");
}
}
// Method 3
// Main driver method
public static void main(String[] args)
{
// Creating an object of above class
// in the main() method
Geek g1 = new Geek();
// Sharing the same object across two Threads
// Creating an object of thread class where
// t1 takes g1
Thread t1 = new Thread(g1);
// Creating an object of thread class where
// t2 takes g1
Thread t2 = new Thread(g1);
// Creating second object of above class
// in the main() method
Geek g2 = new Geek();
// Creating an object of thread class where
// t3 takes g2
Thread t3 = new Thread(g2);
// setName() method is used to set name to the
// thread
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
// start() method is used for initiating the current
// thread
t1.start();
t2.start();
t3.start();
}
}
Output
t1 in block t1 in block t1 end t3 in block t3 in block t3 end t2 in block t2 in block t2 end
2. Using synchronized block method
This method uses a block where the class object is explicitly locked using ClassName.class. It allows better control by synchronizing only specific code.
- Lock is on ClassName.class
- Uses synchronized(ClassName.class)
- More flexible than method-level synchronization.
class Geek implements Runnable {
// Method 1
// @Override
public void run()
{
// Acquire lock on .class reference
synchronized (Geek.class)
// ClassName is name of the class containing method.
{
{
System.out.println(
Thread.currentThread().getName());
System.out.println(
"in block "
+ Thread.currentThread().getName());
System.out.println(
"in block "
+ Thread.currentThread().getName()
+ " end");
}
}
// Method 2
// Main driver method
public static void main(String[] args)
{
// Creating an object of above class
// in the main() method
Geek g1 = new Geek();
// Creating an object of thread class i.e Thread
// 1 where t1 takes g1 object
Thread t1 = new Thread(g1);
// Here, creating Thread 2 where t2 takes g1
// object
Thread t2 = new Thread(g1);
// Creating another object of above class
// in the main() method
Geek g2 = new Geek();
// Now Creating Thread 3 where t3 takes g2 object
Thread t3 = new Thread(g2);
// Ginving custom names to above 3 threads
// using the setName() method
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
// start() method is used to begin execution of
// threads
t1.start();
t2.start();
t3.start();
}
}
Output:
t1
in block t1
in block t1 end
t3
in block t3
in block t3 end
t2
in block t2
in block t2 end
Output explanation: Thread t1 acquired the class lock by entering the synchronized block. Other threads waited until t1 released the lock