📜  Java的类级锁

📅  最后修改于: 2022-05-13 01:55:01.695000             🧑  作者: Mango

Java的类级锁

Java中的每个类都有一个唯一的锁,它只是类级锁。如果一个线程想要执行一个静态同步方法,那么该线程需要一个类级锁。类级锁可防止多个线程在运行时进入该类所有可用实例中的任何一个同步块。这意味着如果在运行时有 10 个类的实例,则只有一个线程一次只能访问任何一个实例的一个方法或块。如果您想保护静态数据,则使用它。

如果一个线程想要执行一个静态同步方法,那么该线程需要一个类级锁。一旦线程获得了类级锁,就可以执行该类的任何静态同步方法。一旦方法执行完成,线程就会自动释放锁。

方法:线程可以通过两种方法获取类级别的锁

  1. 使用同步静态方法。
  2. 使用同步块。

方法 1:使用 同步静态方法

实施:我们有一个 Geek 课程。我们想使用这个类的静态同步方法,线程一进入synchronized方法,线程就获取类级别的锁,其余线程等待获取类监视器锁。当线程退出同步方法时,它会留下一个锁。



public static synchronized int incrementCount()
{
}

例子

Java
// Java program to illustrate class level lock
  
// Main Class
// Implememnting the Runnable interface
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();
    }
}


Java
// Java program to illustrate class level lock
  
// Main Class
// It is implementing the Runnable interface
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 reating 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();
        }
    }


输出
t1
in block t1
in block t1 end
t3
in block t3
in block t3 end
t2
in block t2
in block t2 end

输出说明:

线程 t1 进入静态同步方法并持有 Geek 类的锁。因此,其余线程等待线程 t1 释放 Geek 类上的锁,以便它可以进入静态同步方法。

方法二:使用同步块法

实现:我们有一个“Geek”类。我们要创建一个同步块并传递类名。 class 作为参数告诉哪个类必须在类级别同步。一旦线程进入同步块,线程就在类中获取锁,其余线程等待获取类监视器锁。当线程退出同步块时,它会离开锁。

synchronized (Geek.class) {
    //thread has acquired lock on  Geek class
}

例子

Java

// Java program to illustrate class level lock
  
// Main Class
// It is implementing the Runnable interface
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 reating 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();
        }
    }

输出:

t1
in block t1
in block t1 end
t3
in block t3
in block t3 end
t2
in block t2
in block t2 end

输出说明:

线程 t1 进入了同步块并持有“Geek”类的锁。因此,其余线程等待线程 t1 释放对“Geek”类的锁,以便它可以进入同步块。