ReentrantLock

1、什么是ReentrantLock

        ReentrantLock是Java中的一个可重入锁,它提供了与synchronized关键字类似的功能,但具有更多的灵活性和控制力。

2、实现原理

       ReentrantLock内部使用了一个同步器类AbstractQueuedSynchronizer(AQS),它是实现锁的基础。AQS使用一个FIFO队列(即等待队列)来管理等待锁的线程。当一个线程请求锁时,如果锁已被其他线程占用,该线程将被放入等待队列中,直到锁可用时再进行竞争。

3、优缺点

3.1、ReentrantLock的优点

         3.1.1、ReentrantLock提供了比synchronized关键字更高级的控制和灵活性,可以实现更复杂的锁定机制。
          3.1.2、 它支持可重入锁定的概念,即线程可以多次获取同一个锁,而不会导致死锁。
          3.1.3、 ReentrantLock提供了公平性选项,允许线程按照请求锁的顺序获取锁。这有助于避免线程饥饿现象。
          3.1.4、它支持条件变量,允许线程在特定条件满足之前等待或继续执行。
          3.1.5、 ReentrantLock是java.util.concurrent包的一部分,该包提供了其他有用的并发工具。

3.2、ReentrantLock的缺点

         3.2.1、 与synchronized关键字相比,ReentrantLock需要更多显式的编码。你需要手动使用lock()和unlock()方法来获取和释放锁。
         3.2.2、有可能忘记释放锁,导致潜在的死锁或资源泄漏。需要正确处理异常并使用finally块来确保锁始终被释放。
         3.2.3、 在某些情况下,ReentrantLock可能会稍微增加一些开销,尽管差异通常是可以忽略的。

总体而言,ReentrantLock是Java中管理线程同步的强大工具,提供了更多的控制和灵活性。然而,为了避免潜在的问题,需要谨慎和负责任地使用它。

3.3、公平锁&非公平锁

        ReentrantLock 还提供了公平锁和非公平锁,通过构造方法接受一个可选的 fair 参数(默认非公平锁):当设置为 true 时表示公平锁;false为非公平锁。

       公平锁会按照线程请求锁的顺序来分配锁,确保所有线程都有公平竞争的机会。这有助于避免线程饥饿现象。但是公平锁的效率往往没有非公平锁的效率高,在许多线程访问的情况下,公平锁表现出较低的吞吐量。

 3.4、代码示例

创建一个名为 lock 的ReentrantLock对象,并在构造函数中传入 true 来创建公平锁。在每个线程的任务中,我们使用 lock.lock() 方法获取锁,并在任务完成后使用 lock.unlock() 方法释放锁。

    import java.util.concurrent.locks.ReentrantLock;

    public class ReentrantLockFairExample {
        // 创建公平锁
        private static ReentrantLock lock = new ReentrantLock(true); 

        public static void main(String[] args) {
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    task();
                }
            });

            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    task();
                }
            });

            // 启动线程
            thread1.start();
            thread2.start();
        }

        public static void task() {
            lock.lock();// 获取锁
            try {
                // 执行需要同步的任务
                Thread.sleep(1000); // 模拟处理业务逻辑
                System.out.println("Task..."+ Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();// 释放锁
            }
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值