Do you distinguish between class locks and instance object locks?

Directory of series articles

Article directory

  • Table of Contents of Series Articles
  • Preface
  • 1. What is lock competition?
  • 2. What is a class lock? What is an instance object lock?
  • 3. Locking a class object does not lock the entire class.
  • 4. Summary

Foreword

Java players should all be familiar with locks. The purpose of locking is to ensure the atomicity of operation statements. If you are just learning concurrent programming, are you confused about object locks and class locks? Don’t be afraid! ! ! If you read this article of mine, it will help you solve this confusion~~

1. What is lock contention?

When we use synchronized objects to add locks, and multiple threads try to get the locked object in their own memory space, lock competition will occur. At the moment of competition, only one thread can get it. This locked object is thread safe at this time.
for example:

Suppose there is only one toilet in the bathroom in your dormitory. One night, your roommates all want to go to the toilet at the same time, so you have to fight for this toilet.
Here you and your roommates are the thread;
The toilet bowl in the toilet is the object;
The lock on the toilet door is synchronized;

2. What is a class lock? What is an instance object lock?

Class lock is to lock the members or methods of the class or the class object. The essence of the class lock is to lock the class object.

What is a class object?
A class object is a .class object. A class object records in detail all the information that a programmer has when defining this class, such as attributes, methods, etc.
You can see that the class object is .class, and the source of the class object is the .class file. The .class file is compiled by the javac compiler based on the .java source file. You can understand that there is only one source file, so the class object has only one copy. one serving

Class lock:
Properties or methods modified with static or directly synchronized (class.class) are locking the class.
Instance object lock:
Lock non-static properties or methods

//Add 2000 times to count
class A{<!-- -->
    static int count;
    //Lock the static method, which is to lock the class object
   static synchronized void fun1(){<!-- -->
       for (int i = 0; i < 10000; i + + ) {<!-- -->
           count + + ;
       }
       System.out.println("I am a class method" + count);
   }

   //Lock the instance method, which means locking the instance object.
     synchronized void fun2(){<!-- -->
        for (int i = 0; i < 10000; i + + ) {<!-- -->
            count + + ;
        }
       System.out.println("I am an instance method" + count);
   }
}

3. Locking a class object does not lock the entire class

Whether it is thread safe depends on whether two threads are trying to obtain the same locked object. Even if a lock is added to the class object, it does not mean that one thread has obtained the lock, and other threads can only block and wait. If other threads did not acquire the class lock in the first place, but acquired the instance object lock, then there will not be multiple threads competing to acquire the same object and competing for the same lock.

Look at the following code:

//Thread is not safe. t1 and t2 try to acquire two different objects, one is a class object and the other is an instance object. They do not acquire the same lock, and there is no lock conflict.
public class Test {<!-- -->
    public static void main(String[] args) throws InterruptedException {<!-- -->
        A a = new A();
        //Thread 1 obtains the static modified method
        Thread t1 = new Thread(()->{<!-- -->
           A.fun1();
            try {<!-- -->
                Thread.sleep(10000);
            } catch (InterruptedException e) {<!-- -->
                e.printStackTrace();
            }
        });
        //Thread 2 obtains a non-static modified method
        Thread t2 = new Thread(()->{<!-- -->
           a.fun2();
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }

}
class A{<!-- -->
    static int count;
    //Lock the static method, which is to lock the class object
   static synchronized void fun1(){<!-- -->
       for (int i = 0; i < 10000; i + + ) {<!-- -->
           count + + ;
       }
       System.out.println("I am a class method" + count);
   }

   //Lock the instance method, which means locking the instance object.
     synchronized void fun2(){<!-- -->
        for (int i = 0; i < 10000; i + + ) {<!-- -->
            count + + ;
        }
       System.out.println("I am an instance method" + count);
   }
}

Thread-unsafe, result is less than 20000:

In the following two pieces of code, multiple threads are trying to acquire the same lock.
Look at the following code:
t1 and t2 try to acquire the same lock, instance object lock

//t1 and t2 try to acquire the same lock,
public class Test {<!-- -->
    public static void main(String[] args) throws InterruptedException {<!-- -->
        A a = new A();
        //Thread 1 obtains the non-static modified method
        Thread t1 = new Thread(()->{<!-- -->
// A.fun1();
            a.fun2();
        });
        //Thread 2 obtains a non-static modified method
        Thread t2 = new Thread(()->{<!-- -->
           a.fun2();
// A.fun1();
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }

}
class A{<!-- -->
    static int count;
    //Lock the static method, which is to lock the class object
   static synchronized void fun1(){<!-- -->
       for (int i = 0; i < 10000; i + + ) {<!-- -->
           count + + ;
       }
       System.out.println("I am a class method" + count);
   }

   //Lock the instance method, which means locking the instance object.
     synchronized void fun2(){<!-- -->
        for (int i = 0; i < 10000; i + + ) {<!-- -->
            count + + ;
        }
       System.out.println("I am an instance method" + count);
   }
}


Look at the following piece of code:
t1 and t2 try to obtain the same class lock

public class Test {<!-- -->
    public static void main(String[] args) throws InterruptedException {<!-- -->
        A a = new A();
        //Thread 1 obtains the static modified method
        Thread t1 = new Thread(()->{<!-- -->
           A.fun1();
// a.fun2();
        });
        //Thread 2 obtains the static modified method
        Thread t2 = new Thread(()->{<!-- -->
// a.fun2();
            A.fun1();
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }

}
class A{<!-- -->
    static int count;
    //Lock the static method, which is to lock the class object
   static synchronized void fun1(){<!-- -->
       for (int i = 0; i < 10000; i + + ) {<!-- -->
           count + + ;
       }
       System.out.println("I am a class method" + count);
   }

   //Lock the instance method, which is to lock the instance object
     synchronized void fun2(){<!-- -->
        for (int i = 0; i < 10000; i + + ) {<!-- -->
            count + + ;
        }
       System.out.println("I am an instance method" + count);
   }
}


4. Summary

Whether multi-thread security is safe depends not only on the properties modified by synchronized, because any object in Java can be modified by synchronized. The key lies in whether multiple threads are trying to obtain the same lock object. If it is the same lock, the lock will be sent. Conflict-free, thread-safe. Otherwise, there is no lock conflict and the thread is unsafe.
So don’t be confused by the names of class locks and object locks. Just look at whether multiple threads are acquiring the same lock. If it is the same instance object lock, it is thread safe; if it is the same class object lock, it is thread safe; If one thread acquires the class lock and one thread acquires the instance object lock, it is not safe.