Java多线程之显示锁和内置锁总结详解

Java多线程之显示锁和内置锁总结详解

前言

随着现代计算机的发展,CPU的速度和核心数量逐渐增加,让多线程编程变得越来越重要。Java作为一门支持多线程的语言,在多线程编程方面也提供了一系列的API和机制。本文将重点介绍Java中的两种锁:显示锁和内置锁,并对它们进行详细分析和对比。

什么是锁?

在多线程编程中,为了保证共享资源的正确访问,我们经常需要对这些共享资源进行加锁操作,这时就需要使用锁机制。锁机制主要用于三个目的:

  1. 互斥:同一时刻只允许一个线程访问锁保护的资源;
  2. 可见性:一个线程修改了锁保护的共享变量,其他线程可以看到这个修改;
  3. 有序性:锁的获取和释放具有一定的顺序性,以保证程序正确性。

显示锁

显示锁是Java提供的一种手动管理锁的机制,最主要的类是 java.util.concurrent.locks.Lock。Lock接口定义了两个基本方法,分别是 lock()unlock()。在代码块中使用Lock锁进行同步时,需要手动获取锁和释放锁,代码示例:

Lock lock = new ReentrantLock();
...
lock.lock();
try {
    // 执行需要同步的操作
} catch (Exception e) {
    // 异常处理
} finally {
    lock.unlock();
}

显示锁相比于内置锁更加灵活,它支持条件变量,可以响应中断请求,同时也支持读写锁,可以控制读写操作的并发访问等。

内置锁

内置锁是Java的默认锁机制,也称为 synchronized 同步块,它是Java中最简单和最常见的同步机制之一。内置锁的锁对象是调用该同步块的对象,同一时刻只有一个线程能够获取锁,其他线程需要等待该锁的释放才能继续执行。示例代码:

synchronized (obj) {
    // 执行需要同步的操作
}

内置锁的优点是使用方便,不需要手动获取和释放锁,自动管理。缺点是功能相对简单,只能支持最基本的互斥性。

总结

  1. 显示锁是Java提供的一种手动管理锁的机制,Lock接口定义了两个基本方法;
  2. 内置锁是Java默认的锁机制,也称为synchronized同步块;
  3. 显示锁比内置锁更加灵活,支持条件变量,可以响应中断请求,同时也支持读写锁;
  4. 内置锁使用方便,不需要手动获取和释放锁,自动管理。但功能相对简单,只能支持最基本的互斥性。

示例

示例一:使用显示锁实现多线程同步

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SyncTest {

    private int count = 0;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public void decrement() {
        lock.lock();
        try {
            count--;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest = new SyncTest();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                syncTest.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                syncTest.decrement();
            }
        });

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(syncTest.count);
    }
}

该示例使用显示锁来保证 count 总是在多线程环境下正确,Lock.lock()方法获取锁,try...finally 语句中的 unlock() 方法释放锁。运行该程序会产生 0 的输出,证明了程序的正确性。

示例二:使用内置锁实现多线程同步

public class SyncTest {

    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized void decrement() {
        count--;
    }

    public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest = new SyncTest();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                syncTest.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                syncTest.decrement();
            }
        });

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(syncTest.count);
    }
}

该示例使用内置锁来保证 count 总是在多线程环境下正确,使用 synchronized 对方法进行同步。运行该程序会产生 0 的输出,证明了程序的正确性。

结语

本文对Java中的显示锁和内置锁进行了详细的介绍和比较,并给出了代码示例。在多线程编程中,锁机制是保证程序正确性的重要手段,使用锁机制时需要根据实际情况进行选择。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程之显示锁和内置锁总结详解 - Python技术站

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

相关文章

  • 创建一个Java的不可变对象

    创建一个Java的不可变对象,需要经过以下步骤: 1. 声明类为final 为了防止子类继承和重写类中的方法,将类声明为final。 2. 声明所有的属性为私有的final类型 使用final类型声明属性,并且将其设为私有属性,这样无法修改。 public final class ImmutableObject { private final int age…

    Java 2023年5月26日
    00
  • Java class文件格式之方法_动力节点Java学院整理

    Java class文件格式之方法_动力节点Java学院整理 在Java中,每个方法都有一个对应的Java虚拟机指令集。在Java源代码被编译成Java字节码之后,它们会被组织成一个或多个Java类文件。这些Java类文件都采用类似的格式进行组织,即Java class文件格式。 Java class文件格式中包含了一些关于Java类的元信息,诸如类名、超类…

    Java 2023年5月20日
    00
  • Nginx Tomcat负载均衡动静分离原理解析

    Nginx Tomcat负载均衡动静分离原理解析 1. 前置知识 在理解本文提到的负载均衡和动静分离原理之前,需要先了解以下相关概念: HTTP协议:HyperText Transfer Protocol,超文本传输协议,是互联网上应用最为广泛的一种网络协议。 静态资源和动态资源: 静态资源:相对固定的文件,如HTML、CSS、JavaScript等。 动态…

    Java 2023年6月2日
    00
  • java 文件上传(单文件与多文件)

    好的。对于Java文件上传,常见的方式有单文件上传和多文件上传两种。 一、单文件上传 1.前端通过表单实现文件选择和提交操作,后端利用Apache的FileUpload组件进行接收处理。 <form action="upload" enctype="multipart/form-data" method=&quo…

    Java 2023年5月20日
    00
  • JDBC链接数据库的几个步骤

    JDBC 是Java Database Connectivity的缩写,意为Java数据库连通性,是Java语言中访问数据库的一种技术。以下是JDBC链接数据库的几个步骤以及示例: 步骤一:加载数据库驱动 在Java程序中要想使用某个数据库的API,就必须先装载这个数据库的驱动程序。 try { // 加载MySQL驱动 Class.forName(&quo…

    Java 2023年5月20日
    00
  • Java实现二分搜索树的示例代码

    下面我将详细讲解“Java实现二分搜索树的示例代码”的完整攻略。 什么是二分搜索树? 首先,我们需要明确什么是二分搜索树(BST)。 二分搜索树是一种二叉树,其中每个节点都有一个键值,且每个节点的键值都大于左子树中任意一个节点的键值,小于右子树中任意一个节点的键值。这种性质使得查找、插入、删除节点的操作都可以在时间复杂度为O(logN)的时间内完成,非常适合…

    Java 2023年5月23日
    00
  • 利用Java的Struts框架实现电子邮件发送功能

    利用Java的Struts框架实现电子邮件发送功能 在Struts框架中,可以使用JavaMail实现电子邮件的发送。下面是实现电子邮件发送的完整攻略: 步骤1:导入JavaMail和相关依赖 要使用JavaMail,需要将相关的jar包导入项目中。可以下载JavaMail的jar包和JAF(Java Activation Framework)的jar包,导…

    Java 2023年5月20日
    00
  • java实现投票程序设计

    Java实现投票程序设计攻略 1. 了解需求 在实现投票程序之前,我们需要明确一下需求。例如: 需要设计投票选项,可以通过界面展示 需要统计投票信息,包括投票人数和每个选项的得票数 需要控制每个人只能投一次票 需要友好的界面和交互逻辑 2. 设计数据结构 针对以上需求,我们可以先设计出如下的数据结构: public class Option { privat…

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