📜  Java的对象级锁与类级锁

📅  最后修改于: 2021-09-14 02:04:46             🧑  作者: Mango

Synchronized 是仅适用于方法和块而不适用于类和变量的修饰符。如果多个线程试图同时操作同一个Java对象,那么可能会出现数据不一致问题来解决这个问题,我们应该使用“ synchronized ”关键字。如果一个方法或块声明为同步的,那么一次只允许一个线程在给定的对象上执行该方法或块,以便解决数据不一致问题。内部同步的概念是通过使用锁来实现的。 Java中的每个对象都有一个唯一的锁。每当我们使用’ synchronized ‘关键字时,只有锁的概念才会出现。

如果一个线程想要先在给定的对象上执行同步方法,它必须在线程获得锁后获得该对象的锁,然后才允许在该对象上执行任何同步方法。内部获取和释放锁由 JVM 负责,程序员不负责此活动。当线程在给定对象上执行同步方法时,其余线程不允许在同一对象上同时执行任何同步方法。但允许剩余线程同时执行非同步方法。

对象级锁就是在Java中每个对象都有一个独特的锁,不过对象的机制级锁。如果一个线程想要在给定的对象上执行同步方法,那么一旦线程获得对象级锁,线程首先需要对象级锁,然后允许在给定对象上执行任何同步方法,一旦方法执行完成自动线程释放该对象的锁。

例子:

Java
// Java program to illustrate Object Level Lock Concept
 
// Import required packages
import java.io.*;
import java.util.*;
 
// Class 1
// Helper Class 1
// Consists of synchronized method wish
class Display {
 
    // Declaring Non-static wish method
    public void wish(String name)
    {
 
        // synchronizing wish method
        // and getting the lock of current object
        synchronized (this)
        {
 
            for (int i = 1; i <= 10; i++) {
 
                // display message only
                System.out.print("Good Morning: ");
 
                // Try block to check. for exceptions
                try {
 
                    // Putting thread on sleep for specified
                    // time
                    // usig the sleep() method
                    Thread.sleep(1000);
                }
 
                // Catch block to handle the exceptions
                catch (InterruptedException e) {
 
                    // Print the occurred exception/s
                    System.out.println(e);
                }
                // Display message only
                System.out.println(name);
            }
        }
    }
}
 
// Class 2
// Helper Class 2 (extending main Thread Class)
// myThread with override the run method and
// consists of parameterized constructor
class myThread extends Thread {
    // member variable of this class
    Display d;
    String name;
 
    // Constructor(Parameterized) of this class
    myThread(Display d, String name)
    {
 
        // this keyword refers to currrent object itself
        this.d = d;
        this.name = name;
    }
 
    // run() method for thread
    public void run()
    {
 
        // Calling wish method of display class
        d.wish(name);
    }
}
 
// Class 3
// Main Class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating display class(Class 1) object
        // in the main() method
        Display d = new Display();
 
        // Creating thread objects in main method()
        myThread t1 = new myThread(d, "Dhoni");
        myThread t2 = new myThread(d, "Yuvraj");
 
        // Starting the threads using the start() method
        t1.start();
        t2.start();
    }
}


Java
// java program to illustrate Class Level Lock Concept
 
// Importing required packages
import java.io.*;
import java.util.*;
 
// Class 1
// Helper Class
// Consist of synchronized method wish
class Display {
 
    // Declaring static wish method
    public static void wish(String name)
    {
 
        // synchronizing wish method
        // and getting the lock of display class
        synchronized (Display.class)
        {
 
            for (int i = 1; i <= 10; i++) {
 
                // Display message only
                System.out.print("Good Morning: ");
 
                // Try block to check for exceptions
                try {
                    // Putting thread on sleep for specified
                    // time
                    //  using the sleep() method
                    Thread.sleep(1000);
                }
 
                // Catch block to handle the exception
                catch (InterruptedException e) {
 
                    // Throwing exception
                    System.out.println(e);
                }
                // Display message
                System.out.println(name);
            }
        }
    }
}
 
// C;asss 2
// Helper Class (extends the Thread class)
// myThread with override the run method
// as per our requirements it also consists
// of parameterised constructor
class myThread extends Thread {
    // Member variables of this class
    Display d;
    String name;
 
    // Constructor of this class
    myThread(Display d, String name)
    {
 
        // This keyword refers to current object itself
        this.d = d;
        this.name = name;
    }
 
    // run method for thread/s
    public void run()
    {
 
        // Calling wish method of display class
        d.wish(name);
    }
}
 
// Class 3
// Main Class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating Display class(Class 1) object
        // in the main() method
        Display d = new Display();
 
        // Creating a thread objects
        myThread t1 = new myThread(d, "Dhoni");
        myThread t2 = new myThread(d, "Yuvraj");
 
        // Starting the threads using start() method
        t1.start();
        t2.start();
    }
}


类级锁是一种机制,其中Java中的每个类都有一个唯一的锁,它只不过是一个类级锁。如果线程想要执行静态同步方法,那么一旦线程获得类级锁,则该线程需要类级锁,则允许执行该类的任何静态同步方法。一旦方法执行完成,线程就会自动释放锁。当线程执行静态同步方法时,其余线程不允许同时执行该类的任何静态同步方法。

例子:

Java

// java program to illustrate Class Level Lock Concept
 
// Importing required packages
import java.io.*;
import java.util.*;
 
// Class 1
// Helper Class
// Consist of synchronized method wish
class Display {
 
    // Declaring static wish method
    public static void wish(String name)
    {
 
        // synchronizing wish method
        // and getting the lock of display class
        synchronized (Display.class)
        {
 
            for (int i = 1; i <= 10; i++) {
 
                // Display message only
                System.out.print("Good Morning: ");
 
                // Try block to check for exceptions
                try {
                    // Putting thread on sleep for specified
                    // time
                    //  using the sleep() method
                    Thread.sleep(1000);
                }
 
                // Catch block to handle the exception
                catch (InterruptedException e) {
 
                    // Throwing exception
                    System.out.println(e);
                }
                // Display message
                System.out.println(name);
            }
        }
    }
}
 
// C;asss 2
// Helper Class (extends the Thread class)
// myThread with override the run method
// as per our requirements it also consists
// of parameterised constructor
class myThread extends Thread {
    // Member variables of this class
    Display d;
    String name;
 
    // Constructor of this class
    myThread(Display d, String name)
    {
 
        // This keyword refers to current object itself
        this.d = d;
        this.name = name;
    }
 
    // run method for thread/s
    public void run()
    {
 
        // Calling wish method of display class
        d.wish(name);
    }
}
 
// Class 3
// Main Class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating Display class(Class 1) object
        // in the main() method
        Display d = new Display();
 
        // Creating a thread objects
        myThread t1 = new myThread(d, "Dhoni");
        myThread t2 = new myThread(d, "Yuvraj");
 
        // Starting the threads using start() method
        t1.start();
        t2.start();
    }
}

Class Level Lock

Object Level Lock

This lock can be used when we want to prevent multiple threads to enter the synchronized block of available instances on runtime.  This lock is used when we want a non-static method or non-static block of our code should be accessed by only one thread at a time.
This lock is used to make static data thread-safe. This lock is used to make non-static data thread-safe.
Multiple objects of a particular class may exist but there is always one class’s class object lock available. Every object the class have their own lock. 

We can get a class level lock as follows:

public class GFG {

  public void m1( ) {

     synchronized (GFG.class) {

    // some line of code 

  }

}

We can get object level lock as follows:

public class GFG {

  public void m1( ) {

     synchronized (this) {

        // some line of code

     }

  }

}