一起聊聊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日

相关文章

  • JpaRepository如何实现增删改查并进行单元测试

    JpaRepository是Spring Data JPA中的一个接口,该接口为开发人员提供了一种简单的方式来实现增删改查等常见操作。下面是JpaRepository如何实现增删改查并进行单元测试的完整攻略。 1. 增加数据 JpaRepository提供了一个save()方法来保存一个实体对象。该方法可以用于添加数据。以下是示例代码: @Service p…

    Java 2023年5月20日
    00
  • 详解APP微信支付(java后台_统一下单和回调)

    详解APP微信支付(java后台_统一下单和回调) 一、前言 在移动APP中,使用微信支付功能是非常常见的需求,而且使用微信支付也是比较方便和快捷的。本文将详细介绍如何在Java后台中实现微信支付的功能。主要包括两部分:统一下单和回调。本文介绍的支付接口都是官方的API接口,并采用了最新的V3版本。 二、统一下单 下单接口是微信支付功能的核心,接口名称为:h…

    Java 2023年5月27日
    00
  • 计算机二级考试java软件操作教程 教大家如何学习java

    计算机二级考试Java软件操作教程 为什么学习Java? Java是一门跨平台的编程语言,在开发Web应用、移动应用、桌面应用等众多领域都有广泛应用。学习Java可以让程序员扩展自己的技能树,更好地适应市场需求。而计算机二级考试中也有Java相关的考察内容,学习Java可以更好地准备考试。 学习Java的基本步骤 下载安装Java开发环境(JDK)和集成开发…

    Java 2023年5月20日
    00
  • Android指纹解锁方法解析

    Android指纹解锁方法解析 简介 在 Android 6.0(API level 23)及以上版本中,Google 加入了指纹识别技术,让 Android 设备拥有了指纹解锁的功能。在 Android 开发中,可以通过使用指纹解锁 API 来实现指纹解锁功能。本攻略将详细介绍如何在 Android 应用中使用指纹解锁 API 实现指纹解锁功能。 指纹解锁…

    Java 2023年5月26日
    00
  • Java实现基于JDBC操作mysql数据库的方法

    下面我将详细讲解Java实现基于JDBC操作mysql数据库的方法的完整攻略,包括如何连接数据库、执行SQL语句、关闭资源等步骤。 1. 引入JDBC的依赖 在Java程序中使用JDBC操作mysql数据库,需要引入mysql-connector-java的依赖。可以在Maven中添加如下依赖: <dependency> <groupId&…

    Java 2023年5月19日
    00
  • java中创建写入文件的6种方式详解与源码实例

    Java中创建和写入文件的6种方式详解与源码实例 在Java中,我们可以使用多种方式来创建和写入文件。下面将详细介绍Java中创建和写入文件的6种方式,并提供代码示例。 1. 通过FileOutputStream写入文件 import java.io.*; public class FileOutputStreamExample { public stati…

    Java 2023年5月20日
    00
  • Maven实战之搭建Maven私服和镜像的方法(图文)

    这里详细讲解一下“Maven实战之搭建Maven私服和镜像的方法(图文)”的完整攻略。 一、搭建Maven私服 1. 下载Nexus3 首先需要从Nexus3的官网上下载最新版的Nexus3,下载地址为:https://www.sonatype.com/nexus-repository-oss。 2. 安装Nexus3 下载完成后需要进行安装,具体步骤为解压…

    Java 2023年5月20日
    00
  • 一文详解Spring security框架的使用

    一文详解Spring security框架的使用 Spring Security是一个基于Spring框架实现的权限管理框架,支持基于角色的访问控制和安全性方面的许多其他功能,如认证、授权等等。本文将对Spring Security的使用进行详细讲解。 Spring Security的配置 在使用Spring Security之前,首先需要在pom.xml文…

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