利用aqs构建一个自己的非公平独占锁

功能

具备基本的加锁、解锁功能,并且是非公平的(即允许插队)。

代码

java 复制代码
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class MyNonfairLock {
    // 内部同步器类
    private static class Sync extends AbstractQueuedSynchronizer {
        // 尝试获取锁
        @Override
        protected boolean tryAcquire(int acquires) {
            // 非公平锁直接尝试获取,不考虑队列中是否有等待线程
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                // CAS 操作尝试获取锁
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 可重入支持
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

        // 尝试释放锁
        @Override
        protected boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        // 是否被当前线程独占
        @Override
        protected boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }
    }

    // 创建同步器实例
    private final Sync sync = new Sync();

    // 加锁方法
    public void lock() {
        sync.acquire(1);
    }

    // 尝试加锁
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    // 解锁方法
    public void unlock() {
        sync.release(1);
    }

    // 查询当前线程是否持有锁
    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }

    // 查询锁是否被任何线程持有
    public boolean isLocked() {
        return sync.getState() != 0;
    }
}
  1. 非公平性实现:

在 tryAcquire 方法中,直接尝试获取锁(通过 CAS 操作),不考虑等待队列中是否有其他线程在等待

这与公平锁的区别在于公平锁会先检查队列中是否有等待线程

  1. 可重入支持:

如果当前线程已经是锁的持有者,则增加 state 计数

释放锁时需要释放相同次数

  1. 状态管理:

state = 0 表示锁未被占用

state > 0 表示锁被占用,且数值表示重入次数

  1. 独占模式:

只允许一个线程持有锁

使用 setExclusiveOwnerThread 和 getExclusiveOwnerThread 来跟踪锁的持有者

使用示例

java 复制代码
public class MyLockExample {
    private static final MyNonfairLock lock = new MyNonfairLock();
    private static int counter = 0;

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            for (int i = 0; i < 10000; i++) {
                lock.lock();
                try {
                    counter++;
                } finally {
                    lock.unlock();
                }
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("Final counter value: " + counter); // 应该输出20000
    }
}
相关推荐
码路飞3 小时前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
SimonKing3 小时前
OpenCode AI编程助手如何添加Skills,优化项目!
java·后端·程序员
Seven975 小时前
剑指offer-80、⼆叉树中和为某⼀值的路径(二)
java
怒放吧德德16 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
雨中飘荡的记忆18 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
心之语歌20 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
华仔啊21 小时前
Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅
java·后端
ray_liang1 天前
用六边形架构与整洁架构对比是伪命题?
java·架构
Ray Liang1 天前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解1 天前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端