利用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
    }
}
相关推荐
LiRuiJie3 分钟前
深入剖析Spring Boot / Spring 应用中可自定义的扩展点
java·spring boot·spring
爬虫程序猿11 分钟前
利用 Java 爬虫获取淘宝商品 SKU 详细信息实战指南
java·开发语言·爬虫
茶本无香44 分钟前
RequestContextFilter介绍
java·spring·filter·requestcontext
iナナ1 小时前
初识JVM
java·jvm
m0_570466411 小时前
代码随想录算法训练营第二十八天 | 买卖股票的最佳实际、跳跃游戏、K次取反后最大化的数组和
java·开发语言·算法
ST.J2 小时前
swing笔记
java·笔记
菩提树下的凡夫2 小时前
瑞芯微RV1126目标识别算法Yolov8的部署应用
java·算法·yolo
爱隐身的官人2 小时前
新后端漏洞(上)- Java RMI Registry反序列化漏洞
java·反序列化漏洞
叫我阿柒啊2 小时前
从Java全栈到前端框架:一次真实的面试对话与技术解析
java·javascript·typescript·vue·springboot·react·前端开发