java多线程加锁的三种方式

原创admin 分类:热门问答 0

java多线程加锁的三种方式

在Java多线程编程中,线程安全是一个不可忽视的问题。为了保证共享资源在并发访问时的完整性和一致性,我们需要使用加锁机制来控制线程对资源的访问。本文将详细介绍Java中常用的三种多线程加锁方式:synchronized关键字、ReentrantLock类以及ReadWriteLock类,并提供相应的代码案例和使用场景分析。

1. synchronized关键字【1】

定义与目的

synchronized是Java中的一个关键字,用于创建互斥锁,防止多个线程同时访问共享资源。它可以修饰方法或者代码块,确保同一时间只有一个线程能够执行特定的代码段。

使用条件

  • 当多个线程尝试访问用synchronized修饰的方法或代码块时,只有一个线程能够获取锁并执行。
  • 如果一个线程已经获取了锁,其他线程将被阻塞,直到锁被释放。

核心类与方法

  • synchronized关键字本身不对应特定的类或方法,它是Java语言内置的语法结构。

使用场景

  • 当需要简单快速地同步单个方法或代码块时,synchronized是一个好的选择。
  • 它适用于锁竞争不激烈,且对性能要求不是特别高的场景。

代码案例

public class TicketSeller {
    private int ticketsAvailable = 100;

    public synchronized void sellTicket() {
        if (ticketsAvailable > 0) {
            ticketsAvailable--;
            System.out.println("Ticket sold: " + ticketsAvailable);
        }
    }
}

2. ReentrantLock类【1】

定义与目的

ReentrantLockjava.util.concurrent.locks包中的一个类,它是一个可重入的互斥锁。与synchronized相比,ReentrantLock提供了更灵活的锁操作,如尝试非阻塞地获取锁、可中断的锁获取、公平性选择等。

使用条件

  • 当需要更复杂的锁控制,如尝试获取锁、定时等待、中断等待等场景时,ReentrantLock是更合适的选择。

核心类与方法

  • ReentrantLock类提供了lock()unlock()tryLock()lockInterruptibly()等方法来控制锁的获取和释放。

使用场景

  • 在锁竞争较为激烈,或者需要更细粒度控制锁行为的场景下,ReentrantLock是首选。

代码案例

import java.util.concurrent.locks.ReentrantLock;

public class Account {
    private double balance;
    private final ReentrantLock lock = new ReentrantLock();

    public void deposit(double amount) {
        lock.lock();
        try {
            balance += amount;
        } finally {
            lock.unlock();
        }
    }

    public void withdraw(double amount) {
        lock.lockInterruptibly();
        try {
            balance -= amount;
        } finally {
            lock.unlock();
        }
    }
}

3. ReadWriteLock类【1】

定义与目的

ReadWriteLockjava.util.concurrent.locks包中的一个接口,它维护一对关联的锁:一个用于读取,一个用于写入。多个线程可以同时获取读锁,但写锁是互斥的。这种锁适用于读多写少的场景,可以提高并发性能。

使用条件

  • 当共享资源的读操作远多于写操作时,使用ReadWriteLock可以提高系统的并发性能。

核心类与方法

  • ReentrantReadWriteLockReadWriteLock接口的一个实现,它提供了readLock()writeLock()方法来获取读锁和写锁。

使用场景

  • 适用于缓存等读操作频繁,写操作较少的应用场景。

代码案例

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Cache {
    private final Object data;
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();

    public Cache(Object data) {
        this.data = data;
    }

    public Object read() {
        rwLock.readLock().lock();
        try {
            return data;
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public void write(Object newData) {
        rwLock.writeLock().lock();
        try {
            data = newData;
        } finally {
            rwLock.writeLock().unlock();
        }
    }
}

对比表格

特性/锁类型 synchronized ReentrantLock ReadWriteLock
实现方式 关键字 接口
灵活性
可中断性
公平性 否(非公平默认) 可配置
锁获取方式 阻塞式 多种方式 读多写少优化
适用场景 简单同步 复杂同步控制 读多写少

通过上述对比表格,我们可以看到每种锁机制都有其特定的使用场景和优势。在实际开发中,我们需要根据具体的需求和场景来选择合适的加锁方式,以确保线程安全的同时,也能保持程序的性能和效率。

相关文章

猜你喜欢

领取相关Java架构师视频资料

网络安全学习平台视频资料