📜  Java中的对象级和类级锁

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

Java中的对象级和类级锁

同步:

同步是仅用于方法和块的修饰符。在同步修饰符的帮助下,我们可以限制共享资源只能由一个线程访问。当两个或更多线程需要访问共享资源时,会出现一些数据丢失,即数据不一致。我们可以在多个线程之间实现数据一致性的过程称为同步。

为什么需要同步?

让我们假设您是否有两个线程正在读取和写入相同的“资源”。假设有一个名为 geek 的变量,并且您希望一次只有一个线程应该访问该变量(原子方式)。但是如果没有 synchronized 关键字,你的线程 1 可能看不到线程 2 对 geek 所做的更改,或者更糟糕的是,它可能只更改了一半导致数据不一致的问题。这不是您在逻辑上所期望的。防止这些错误所需的工具是同步。

在同步中,线程上有两种类型的锁:

  • 对象级锁: Java中的每个对象都有一个唯一的锁。每当我们使用 synchronized 关键字时,只有锁的概念才会出现。如果一个线程想要执行给定对象上的同步方法。首先,它必须锁定该对象。一旦线程获得锁,就可以在该对象上执行任何同步方法。一旦方法执行完成,线程会自动释放锁。内部获取和释放锁由 JVM 负责,程序员不对这些活动负责。让我们看看下面的程序来理解对象级锁:
JAVA
// Java program to illustrate
// Object lock concept
class Geek implements Runnable {
    public void run() { Lock(); }
    public void Lock()
    {
        System.out.println(
            Thread.currentThread().getName());
        synchronized (this)
        {
            System.out.println(
                "in block "
                + Thread.currentThread().getName());
            System.out.println(
                "in block "
                + Thread.currentThread().getName()
                + " end");
        }
    }
 
    public static void main(String[] args)
    {
        Geek g = new Geek();
        Thread t1 = new Thread(g);
        Thread t2 = new Thread(g);
        Geek g1 = new Geek();
        Thread t3 = new Thread(g1);
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
}


JAVA
// Java program to illustrate class level lock
class Geek implements Runnable {
    public void run() { Lock(); }
 
    public void Lock()
    {
        System.out.println(
            Thread.currentThread().getName());
        synchronized (Geek.class)
        {
            System.out.println(
                "in block "
                + Thread.currentThread().getName());
            System.out.println(
                "in block "
                + Thread.currentThread().getName()
                + " end");
        }
    }
 
    public static void main(String[] args)
    {
        Geek g1 = new Geek();
        Thread t1 = new Thread(g1);
        Thread t2 = new Thread(g1);
        Geek g2 = new Geek();
        Thread t3 = new Thread(g2);
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
}


输出
t1
t3
t2
in block t3
in block t1
in block t3 end
in block t1 end
in block t2
in block t2 end
  • 类级锁: Java中的每个类都有一个唯一的锁,它只不过是一个类级锁。如果一个线程想要执行一个静态同步方法,那么该线程需要一个类级别的锁。一旦线程获得了类级别的锁,就可以执行该类的任何静态同步方法。一旦方法执行完成,线程会自动释放锁。让我们看一下下面的程序以更好地理解:

Java

// Java program to illustrate class level lock
class Geek implements Runnable {
    public void run() { Lock(); }
 
    public void Lock()
    {
        System.out.println(
            Thread.currentThread().getName());
        synchronized (Geek.class)
        {
            System.out.println(
                "in block "
                + Thread.currentThread().getName());
            System.out.println(
                "in block "
                + Thread.currentThread().getName()
                + " end");
        }
    }
 
    public static void main(String[] args)
    {
        Geek g1 = new Geek();
        Thread t1 = new Thread(g1);
        Thread t2 = new Thread(g1);
        Geek g2 = new Geek();
        Thread t3 = new Thread(g2);
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
}
输出
t1
t2
t3
in block t1
in block t1 end
in block t3
in block t3 end
in block t2
in block t2 end

参考: https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html