详解java 对象锁与类锁

我们来详细讲解一下 Java 对象锁和类锁。

什么是对象锁?

在 Java 中,每一个对象都有一个锁,也就是监视器锁(Monitor Lock)。当一个线程访问某个对象的 synchronized 方法或 synchronized 块时,这个线程会试图获得这个对象的锁。获得对象锁后,这个线程才能进入 synchronized 方法或 synchronized 块中执行代码。其他线程必须等待锁的释放才能继续执行。

一个对象锁只保护一个对象的同步方法或同步块。如果一个对象有多个同步方法,每个方法都可以被独立执行,因为每个方法都有自己的对象锁。如果一个线程正在执行某个对象的同步方法,其他线程可以访问该对象的非同步方法,因为这些非同步方法没有竞争这个对象锁。

下面是一个简单的示例代码,通过 synchronized 关键字实现了线程之间的同步:

public class MyThread extends Thread {
    private String threadName;
    private Object object;

    public MyThread(String name, Object obj) {
        threadName = name;
        object = obj;
    }

    public void run() {
        synchronized(object) {
            System.out.println(threadName + " has acquired the object lock.");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(threadName + " is releasing the object lock.");
        }
    }

    public static void main(String[] args) {
        Object obj = new Object();
        MyThread t1 = new MyThread("Thread 1", obj);
        MyThread t2 = new MyThread("Thread 2", obj);
        t1.start();
        t2.start();
    }
}

运行上面的代码,你会发现 Thread 1 和 Thread 2 交替获得和释放了 obj 这个对象的锁。

什么是类锁?

除了对象锁以外,Java 还有一种锁叫做类锁(Class Lock)。当一个线程访问某个类的 synchronized 静态方法或 synchronized(classname) 代码块时,这个线程会获得这个类的 Class 对象的锁。类锁只有一个,因此多个线程访问类的 synchronized 静态方法或 synchronized(classname) 代码块时会相互竞争,而不同的类的 synchronized 静态方法或 synchronized(不同的Class对象) 代码块之间没有竞争关系。

和对象锁一样,类锁也是可重入的,也就是说一个线程已经获得了某个类的锁,那么它可以重复获得该锁,而不用重新等待锁的释放。

下面是一个示例代码,演示了如何使用类锁:

public class ThreadSafeCounter {
    private static int count = 0;

    public static synchronized void increment() {
        System.out.println(Thread.currentThread().getName() + " is running increment().");
        int temp = count;
        temp++;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count = temp;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            ThreadSafeCounter.increment();
        });
        Thread t2 = new Thread(() -> {
            ThreadSafeCounter.increment();
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("The final count is " + count);
    }
}

在上面的示例代码中,我们定义了一个静态方法 increment(),使用 synchronized 关键字修饰,实现了对 count 变量的线程安全访问。在 main 方法中,我们启动了两个线程对 count 变量进行自增操作,由于 increment() 方法使用的是类锁,所以两个线程会相互竞争,保证了对 count 变量的线程安全访问。

通过这两个示例,我们可以更好地理解对象锁和类锁在 Java 中的应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解java 对象锁与类锁 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 使用Dockerfile构建java web环境

    下面我将为您提供“使用Dockerfile构建Java Web环境”的完整攻略。 准备工作 安装Docker 如果您还没有安装Docker,可以先在官网上下载并安装Docker:https://www.docker.com/products/docker-desktop 编写Dockerfile Dockerfile是用于构建Docker镜像的脚本,我们可以…

    Java 2023年6月2日
    00
  • java与js代码互调示例代码

    当需要在Java与JavaScript之间进行代码互调时,可以使用Java在JavaScript中定义的函数来实现该功能。以下是使用Java代码在JavaScript中定义一个函数,并从JavaScript调用该函数的示例代码: 第一步是为Java代码编写一个类,在类中编写一个用于输出信息到控制台的函数: package com.example; publi…

    Java 2023年5月24日
    00
  • java简单实现八叉树图像处理代码示例

    下面我将为您详细讲解“Java简单实现八叉树图像处理代码示例”的完整攻略。 什么是八叉树 八叉树是一种多叉树结构,它的每个非叶子结点都有八个孩子结点。在计算机视觉和计算机图形学中,八叉树被广泛应用于图像处理中的分割和压缩等领域。 八叉树在图像处理中的应用 将一幅图像划分为多个小块是图像处理中的一种重要方法,八叉树就是在图像划分中广泛应用的一种方法。通过将一幅…

    Java 2023年5月19日
    00
  • Java JDK1.7对字符串的BASE64编码解码方法

    Java JDK 1.7版本提供了对字符串进行 BASE64 编码和解码的方法,它们是 java.util.Base64 和 javax.xml.bind.DatatypeConverter。 使用java.util.Base64类进行BASE64编码和解码 java.util.Base64 是 JDK 1.8 新增的类,它提供了两个静态方法 getEnco…

    Java 2023年5月20日
    00
  • 非常实用的Tomcat启动脚本实现方法

    非常实用的Tomcat启动脚本实现方法 在Linux环境下,通常我们会使用启动脚本的方式来启动Tomcat。而对于初学者来说,编写一个完整可靠的启动脚本不是一件容易的事情。本文将介绍一种非常实用的Tomcat启动脚本实现方法,帮助大家快速实现Tomcat的自动启动、关闭、查看状态等操作。 Step 1: 创建启动脚本 首先,我们需要创建一个启动脚本。为了让脚…

    Java 2023年5月19日
    00
  • Hibernate三种状态和Session常用的方法

    下面我为你详细讲解一下Hibernate三种状态和Session常用的方法。 Hibernate三种状态 在Hibernate中,每个对象都有三种状态: 持久化状态(Persistent):对象与数据库中的数据相互关联,当对对象进行改变后,会同步到数据库中。 脱管状态(Detached):对象仍然存在,但它已经和session失去了关联,更改对象不会同步到数…

    Java 2023年5月19日
    00
  • springboot websocket简单入门示例

    让我为你详细介绍一下“Spring Boot WebSocket简单入门示例”的攻略。 简介 Spring Boot WebSocket使得在应用程序中添加实时数据交互功能变得非常容易。WebSocket是一种在单个TCP连接上全双工通信协议,它使得服务器端和客户端之间可以双向通信。下面,我们将演示如何在Spring Boot应用程序中使用WebSocket…

    Java 2023年5月19日
    00
  • java多线程模拟实现售票功能

    Java多线程模拟实现售票功能,主要涉及Java的并发编程和线程同步操作。以下是实现该功能的步骤: 步骤一:创建Ticket类及构造方法 public class Ticket { private int num; public Ticket(int num) { this.num = num; } public int getNum() { return …

    Java 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部