ReentrantLock底层原理、手写Lock锁
发布日期:2021-05-14 12:39:13 浏览次数:16 分类:精选文章

本文共 3499 字,大约阅读时间需要 11 分钟。

ReentrantLock 是一种轻量级锁,由 Java 自行实现,采用自旋锁的原理,无需依赖操作系统。在 JDK 1.5 以前,synchronized 锁较重,效率较低。而 ReentrantLock 则更高效,支持递归。以下是自定义实现 ReentrantLock 的过程:

自定义锁实现

首先,创建一个名为 XdLock 的类,实现 Lock 接口。使用 AtomicReference 记录持有锁的线程,LinkedBlockingQueue 缓存等待线程。

package com.test;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class XdLock implements Lock {
private AtomicReference
cas;
private final LinkedBlockingQueue
queue;
public XdLock() {
cas = new AtomicReference<>();
queue = new LinkedBlockingQueue<>();
}
@Override
public void lock() {
final Thread current = Thread.currentThread();
while (!cas.compareAndSet(null, current)) {
// 进入队列
queue.put(current);
System.out.println(current.getName() + ":进入阻塞");
LockSupport.park();
System.out.println(current.getName() + ":已放开阻塞线程");
// 唤醒时处理
boolean unwrapped = true;
while (unwrapped) {
unwrapped = queue.poll() != null;
if (unwrapped) {
LockSupport.unpark(unwrapped);
}
}
}
}
@Override
public void unlock() {
final Thread current = Thread.currentThread();
if (cas.compareAndSet(current, null)) {
// 唤醒队列中的所有线程
for (Thread t : new LinkedHashSet<>(queue)) {
System.out.println(getCurrent().getName() + ":唤醒线程 " + t.getName());
LockSupport.unpark(t);
}
// 重置队列为空
queue.clear();
}
}
@Override
public Condition newCondition() {
return null; // 简化实现,留空或自定义条件处理
}
// 提供不尝试锁的新方法
@Override
public boolean tryLock() {
return false; // 简化实现
}
// 支持锁的可中断性,但此处简化
@Override
public void lockInterruptibly() throws InterruptedException {
// 类似 lock(),直接进入阻塞
}
// 提供时限的锁获取方式
@Override
public boolean tryLock(final long time, final TimeUnit unit) throws InterruptedException {
return false;
}
// 辅助获取当前线程
private static Thread getCurrent() {
return Thread.currentThread();
}
}

测试实现

编写测试代码,观察多线程行为。

public class LockTest {
private static XdLock lock;
public static void main(String[] args) {
lock = new XdLock();
Runnable task = () -> {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + ":获取锁成功");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getCurrent().getName() + ":解锁成功");
} finally {
lock.unlock();
}
};
long start = System.currentTimeMillis();
for (int i = 0; i < 5; i++) {
new Thread(task).start();
if (i > 0) Thread.sleep(100);
}
System.out.println("总耗时:" + (System.currentTimeMillis() - start));
}
private static Thread getCurrent() {
return Thread.currentThread();
}
}

优化考虑

  • 队列处理优化:使用无参的 _BLK 队列,提高性能。
  • 唤醒批量处理:同时唤醒多个等待线程,减少时间 wasting。
  • 自旋机制:优化自旋队列,提升抢锁效率。
  • 防饥饿机制:在高并发下,增加公平锁的实现。
  • 结论

    通过上述实现,理解了 ReentrantLock 的原理,掌握了轻量级锁的开发技巧。这不仅增进了对 Java 并发编程的理解,还为后续项目提供了实用的开发经验。对于高并发场景,需结合具体需求选择合适的锁机制,以确保程序高效稳定运行。

    上一篇:synchronized 锁升级过程
    下一篇:idea 在Debug 模式中运行语句中函数的方法

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年04月30日 00时19分10秒