可重入锁 ReentrantLock 使用


共计 1631 个字符,预计需要花费 5 分钟才能阅读完成。

ReentrantLock可重入锁)是 Java 中的一种同步机制,它提供了与synchronized关键字相似的功能,但具有更灵活的特性。在多线程编程中,ReentrantLock允许线程在获取锁之后再次获取同一把锁,而不会导致死锁。

ReentrantLock 具有以下特点:

  1. 可重入性:

ReentrantLock是可重入的,这意味着一个线程可以多次获取同一把锁而不会产生死锁。当线程重复获取锁时,它必须相应地释放同样次数的锁,才能完全释放锁资源。

  1. 互斥性:

ReentrantLock保证了线程对共享资源的互斥访问。一次只有一个线程可以持有这把锁,其他线程必须等待锁释放才能获得锁。

  1. 等待可中断:

通过lockInterruptibly()方法,线程可以在等待锁的过程中被中断,而不是一直阻塞等待。这种特性能够避免线程长时间阻塞,提高系统的响应性。

  1. 公平性:

ReentrantLock可以在创建时选择是否公平锁。公平锁是指锁的获取按照请求的顺序进行,而非公平锁则允许插队。公平锁会导致线程切换的开销增加,但能避免饥饿问题。

Sychronized 和 ReentrantLock 比较:

synchronized ReentrantLock
Java中的一个关键字 JDK提供的一个类
JVM层面的锁 API层面的锁
自动加锁与释放锁 需要手动加锁与释放锁
不可获取当前线程是否上锁 可获取当前线程是否上锁isHeldByCurrentThread
非公平锁 公平锁或非公平锁
不可中断 可中断 1:调用设置超时方法tryLock(long timeout ,timeUnit unit) 2:调用lockInterruptibly()放到代码块中,然后调用interrupt()方法可以中断
锁的是对象,锁信息保存在对象头中 int类型的state标识来标识锁的状态
底层有锁升级过程 没有锁升级过程

简单实用案例:

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

public class ReentrantLockExample {
    private final Lock lock = new ReentrantLock();
    private int count = 0;

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

    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockExample example = new ReentrantLockExample();

        // 创建并启动两个线程,分别增加计数器的值
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

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

        // 等待两个线程执行完毕
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 输出最终的计数器值
        System.out.println("Final Count: " + example.getCount());
    }
}

需要注意的是,使用ReentrantLock时,一定要确保在合适的位置释放锁,通常在finally块中释放锁以确保不管是否发生异常都能释放锁资源,避免死锁情况。

提醒:本文发布于108天前,文中所关联的信息可能已发生改变,请知悉!

Tips:清朝云网络工作室

阅读剩余
THE END