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日

相关文章

  • JSON中fastjson、jackson、gson如何选择

    首先需要了解的是,Fastjson、Jackson和GSON都是流行的JavaJSON库。选择哪个库是根据你的项目、环境需求和个人喜好来决定的。以下是跟进项目、需求以及个人偏好来选择JSON库的攻略: 1. 选择Fastjson Fastjson 是由阿里巴巴开发并维护的 JSON 库,速度快,支持 JavaBean、List、List 等复杂对象的JSON…

    Java 2023年5月26日
    00
  • 一文读懂Spring Bean的生命周期

    一文读懂Spring Bean的生命周期 Spring是一款非常流行的Java开发框架,支持面向对象编程、IOC和AOP等高级特性,而Spring Bean是其最基本的组成部分。本文将通过详细讲解Spring Bean的生命周期来帮助读者深入理解Spring框架的工作原理。 什么是Spring Bean? Spring Bean是Spring IoC容器中管…

    Java 2023年5月19日
    00
  • SpringBoot集成SpringSecurity和JWT做登陆鉴权的实现

    下面是详细的讲解和示例: 一、SpringBoot集成SpringSecurity和JWT的基础配置 Spring Security 是一款强大、灵活并且广泛使用的安全框架,它基于 Spring 构建,提供了一种基于角色的访问控制、认证和授权等安全解决方案。而 JWT 是一种轻量级的认证机制,它可以在用户和服务器之间进行授权传递,用于跨域认证。在本文中,我们…

    Java 2023年5月20日
    00
  • 浅谈一下Java为什么不能使用字符流读取非文本的二进制文件

    标题:浅谈一下Java为什么不能使用字符流读取非文本的二进制文件 在Java中,我们通常使用字节流来处理二进制文件。而字符流主要是用来处理文本文件,因为字符流在读取文本文件时,可以自动将字节转换为字符,而读取二进制文件时,字符流就会出现问题。 一、字符流与字节流的区别 字符流的底层还是使用字节流实现的,但字符流在处理文本时通过Java编码转换器将字节转换为字…

    Java 2023年5月20日
    00
  • Java面试题冲刺第三十天–数据库(6)

    “Java面试题冲刺第三十天–数据库(6)”这篇文章主要介绍了关于数据库中的事务控制及其实现方式等内容。下面是该文章的完整攻略: 事务控制 事务是指在数据库中执行的一个操作序列,这些操作要么全部执行成功,要么全部执行失败,不会出现执行了部分操作后停止的情况。事务控制是指保证事务的正确性和完整性,及其一致性的机制。 事务的ACID特性 原子性(Atomici…

    Java 2023年5月19日
    00
  • java获取properties属性文件示例

    当我们需要在Java程序中读取properties属性文件时,通常可以使用java.util.Properties类来实现。下面是实现此操作的完整攻略: 1. 获取properties文件 首先需要获取到带有相关属性的properties文件,可以通过在项目中创建文件或者从外部导入文件的方式进行获取。假设我们已经有了一个示例属性文件”example.prop…

    Java 2023年5月19日
    00
  • Jackson多态序列化图文详解

    Jackson多态序列化是指当JSON数据包含多种不同类型的对象时,如何正确地将这些对象序列化为JSON格式,同时又能保留它们的特定类型信息。 在Java中,可以通过使用Jackson库进行多态序列化。下面是一个完整的攻略: 什么是多态序列化? 多态序列化是指将面向对象编程中的多态特性应用于序列化数据。在Java中,多态是指子类可以替代父类而被当做父类来使用…

    Java 2023年5月26日
    00
  • Java基础教程之String深度分析

    Java基础教程之String深度分析 介绍 Java中的String类是使用最广泛的类之一。了解并掌握String的使用是Java编程必备的基础知识之一。本文将深入剖析String类的工作原理以及相关的操作方法,希望能够对读者有所帮助。 String的工作原理 Java中的String类是不可变类,即一旦创建就不可以修改。这是通过在内存中分配一个固定大小的…

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