一起聊聊Java中13种锁的实现方式

一起聊聊Java中13种锁的实现方式

背景介绍

在Java中使用锁是实现多线程同步的一种常用方式,也是保证程序并发安全的必要手段。本文将对Java中13种锁的实现方式进行详细讲解。

13种锁实现方式

1. synchronized关键字

synchronized关键字是Java中最基本、最常用的锁实现方式。它通过获取对象的锁来控制对对象的访问,进而实现多线程的同步。

public synchronized void synchronizedMethod() {
    // 需要同步的代码块
}

2. ReentrantLock

ReentrantLock是Java中的另一种锁实现方式。它提供了比synchronized更丰富的特性,比如可定时、可中断的锁请求,公平锁等。

private Lock lock = new ReentrantLock();

public void reentrantLockMethod() {
    lock.lock();
    try {
        // 需要同步的代码块
    } finally {
        lock.unlock();
    }
}

3. ReentrantReadWriteLock

ReentrantReadWriteLock在读写操作需要频繁发生时可以提高性能,它是基于ReentrantLock实现的。

private ReadWriteLock lock = new ReentrantReadWriteLock();

public void readMethod() {
    lock.readLock().lock();
    try {
        // 读操作,多线程可以共享访问
    } finally {
        lock.readLock().unlock();
    }
}

public void writeMethod() {
    lock.writeLock().lock();
    try {
        // 写操作,只能有一个线程执行
    } finally {
        lock.writeLock().unlock();
    }
}

4. StampedLock

StampedLock是Java 8中引入的锁实现方式,比ReentrantReadWriteLock性能更高。

private StampedLock lock = new StampedLock();

public void stampedLockMethod() {
    long stamp = lock.readLock();
    try {
        // 读操作,多线程可以共享访问
    } finally {
        lock.unlockRead(stamp);
    }
}

public void stampedWriteLockMethod() {
    long stamp = lock.writeLock();
    try {
        // 写操作,只能有一个线程执行
    } finally {
        lock.unlockWrite(stamp);
    }
}

5. Condition

Condition是Java中的一种比较高级的线程同步方式,它可以协调一组线程的执行。例如,先执行线程A,在执行其它N个线程,最后再执行线程A。

private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();

public void conditionMethod() {
    lock.lock();
    try {
        // 等待信号
        condition.await();
        // 唤醒后执行的代码块
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

public void signalMethod() {
    lock.lock();
    try {
        // 发送信号
        condition.signal();
        // 继续执行后面的代码
    } finally {
        lock.unlock();
    }
}

6. Semaphore

Semaphore是Java中用来实现信号量机制的锁,可以控制对共享资源的访问线程数。

private Semaphore semaphore = new Semaphore(10);

public void method() {
    try {
        semaphore.acquire();
        // 访问共享资源的代码块
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        semaphore.release();
    }
}

7. CountDownLatch

CountDownLatch是一个同步器,可以实现等待线程一组操作完成后再执行某个操作,比如等待多个线程处理完成后再执行某个操作。

private CountDownLatch countDownLatch = new CountDownLatch(5);

public void method() {
    // 业务逻辑处理
    countDownLatch.countDown();
}

public void joinMethod() {
    try {
        countDownLatch.await();
        // 当countDownLatch的计数器减为0时执行的操作
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

8. CyclicBarrier

CyclicBarrier也是一个同步器,它会等待所有线程都执行完成后再执行下一步操作,和CountDownLatch类似,但是它可以重复使用。

private CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
  // 所有线程执行完成后执行的操作
});

public void method() {
    // 业务逻辑处理
    cyclicBarrier.await();
}

9. LockSupport

LockSupport是Java中一种基于线程的锁机制,可以控制线程的阻塞和唤醒。

public void parkMethod() {
    LockSupport.park();
    // 执行后续代码
}

public void unparkMethod() {
    LockSupport.unpark(Thread.currentThread());
}

10. ThreadLocal

ThreadLocal可以实现对线程中数据的隔离和独立访问,每个线程都能存储属于自己的数据。多线程访问同一个ThreadLocal对象时,每个线程都是操作自己的数据,互不干扰。

private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

public void method() {
    threadLocal.set(1);
    // 其它业务代码
    threadLocal.get();
}

11. ReadWriteLock

ReadWriteLock接口提供比synchronizedReentrantLock提供更好的性能,多个线程可以同时进行读操作,但是写操作只能有一个线程执行。

private ReadWriteLock lock = new ReentrantReadWriteLock();   

public void readMethod() {
    lock.readLock().lock();
    try {
        // 读操作,多个线程可以共享访问
    } finally {
        lock.readLock().unlock();
    }
}

public void writeMethod() {
    lock.writeLock().lock();
    try {
        // 写操作,只能有一个线程执行
    } finally {
        lock.writeLock().unlock();
    }
}

12. LongAdder

LongAdder是Java 8中引入的一种高并发计数器,它可以减少多线程竞争,从而提高性能。

private LongAdder longAdder = new LongAdder();

public void increment() {
    longAdder.increment();
}

public long sum() {
    return longAdder.sum();
}

13. AtomicXXX

Java中提供了一系列AtomicXXX类,它们通过原子操作实现了线程安全,比如AtomicInteger

private AtomicInteger atomicInteger = new AtomicInteger();

public void increment() {
    atomicInteger.incrementAndGet();
}

public int get() {
    return atomicInteger.get();
}

示例说明

示例一:ReentrantLock

比如在一个银行转账的场景中,假设有两个账户a和b,需要进行转账操作。在这个过程中,将a和b锁起来,防止其它线程的干扰,就可以使用ReentrantLock。

private ReentrantLock lock = new ReentrantLock();
private Map<String, Integer> accountMap = new HashMap<>();

public void transfer(String fromAccount, String toAccount, Integer amount) {
    lock.lock();
    try {
        Integer fromMoney = accountMap.get(fromAccount);
        Integer toMoney = accountMap.get(toAccount);
        fromMoney -= amount;
        toMoney += amount;
        accountMap.put(fromAccount, fromMoney);
        // 模拟延迟
        Thread.sleep(100);
        accountMap.put(toAccount, toMoney);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

示例二:Semaphore

比如在一个生产者-消费者的场景中,假设生产者最多创建10个商品,每个消费者可以消费1个商品。在这个过程中,生产者和消费者之间需要互相协调,防止生产者创建过多的商品,也防止消费者消费过多的商品,就可以使用Semaphore。

private Semaphore semaphore = new Semaphore(10);

public void producer() {
    try {
        semaphore.acquire();
        // 业务代码:创建商品
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        semaphore.release();
    }
}

public void consumer() {
    try {
        semaphore.acquire();
        // 业务代码:消费商品
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        semaphore.release();
    }
}

总结

Java中共有13种锁实现方式,从synchronizedAtomicXXX类,每种锁都有各自的优缺点。开发者在选择锁实现方式时需要结合实际场景,综合考虑其性能、复杂度等因素,才能选出最合适的锁实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一起聊聊Java中13种锁的实现方式 - Python技术站

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

相关文章

  • JVM自定义类加载器在代码扩展性实践分享

    下面是“JVM自定义类加载器在代码扩展性实践分享”的完整攻略。 什么是自定义类加载器 Java平台中,系统默认提供了三种类加载器:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader,这些类加载器会按照固定的顺序依次加载类。 自定义类加载器,是指程序员自己编写的类加载器,用于满足特定的需求,例如…

    Java 2023年6月15日
    00
  • Java面试题之基本语法(图解)

    Java 面试题之基本语法攻略 1. 概述 本篇攻略将涵盖 Java 基本语法面试题的相关知识点,包括数据类型、流程控制、对象、类、接口等方面。这些知识点是 Java 程序员必须了解和掌握的内容,在面试中也是常常被提及到的话题。掌握这些知识点能够让你在面试中更加得心应手。 本攻略分为以下几个部分: 数据类型 流程控制 对象与类 接口 2. 数据类型 Java…

    Java 2023年5月23日
    00
  • spring-boot-plus V1.4.0发布 集成用户角色权限部门管理(推荐)

    Spring Boot Plus V1.4.0发布 Spring Boot Plus是一个基于SpringBoot的项目快速开发脚手架,版本 V1.4.0 提供了用户角色权限部门管理的集成,方便用户快速搭建管理后台。 安装 首先,我们需要安装Java和Maven,参考:- Java 安装教程- Maven 安装教程 Spring Boot Plus 是通过M…

    Java 2023年5月20日
    00
  • Java的Struts框架报错“ServletException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“ServletException”错误。这个错误通常由以下原因之一起: 配置错误:如果配置文件中没有正确配置,则可能会出现此错误。在这种情况下,检查文件以解决此问题。 代码错误:如果代码中存在错误,则可能会出现此错误。在这种情况下,需要检查代码以解决此问题。 以下是两个实例: 例 1 如果配置文件中没有正确配置…

    Java 2023年5月5日
    00
  • 如何使用Java Security Manager?

    如何使用Java SecurityManager? Java SecurityManager 是一个Java安全工具,可以允许或禁止Java应用程序执行某些操作。本文将为您详细讲解如何使用Java SecurityManager,包括设置SecurityManager,创建权限策略文件,以及使用示例说明。 1. 设置SecurityManager 首先,要想…

    Java 2023年5月11日
    00
  • kafka topic 权限控制(设置删除权限)

    Kafka是一个分布式流处理平台,提供了强大的消息队列功能,它的漏洞和配置不良问题可能会导致未授权访问和数据泄露等问题。本篇攻略将详细介绍如何对Kafka Topic进行权限控制,并设置删除权限,帮助您避免可能的安全隐患。 准备工作 在开始本攻略之前,需要确保您已经完成以下准备工作: 安装Kafka。 创建一个Kafka集群。 熟悉Kafka Topic基本…

    Java 2023年6月2日
    00
  • Java经典面试题汇总:JVM

    Java经典面试题汇总:JVM JVM是什么? JVM(Java Virtual Machine,即Java虚拟机)是Java平台的一个重要组成部分,也是整个Java技术体系的核心所在。它是Java实现“一次编写,到处运行”的重要基石,同时也是Java能够拥有强大的跨平台能力的主要原因之一。 当我们运行Java程序时,JVM会解释并执行Java字节码,最终把…

    Java 2023年5月23日
    00
  • 手把手教你怎么创建spring项目

    创建Spring项目的步骤如下: 步骤一:安装IDE 首先,我们需要在本地安装一个IDE(Integrated Development Environment),例如Eclipse、IntelliJ IDEA、Spring Tool Suite等。这里以Eclipse为例进行讲解。进入Eclipse,按照提示进行安装和配置即可。 步骤二:创建Maven工程 …

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