利用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
    }
}
相关推荐
风象南26 分钟前
SpringBoot模块化开发的5种组织方式
java·spring boot·后端
冬天vs不冷30 分钟前
Java基础(二):八种基本数据类型详解
java·开发语言·php
x_feng_x3 小时前
Java从入门到精通 - 常用API(一)
java·开发语言·python
钢铁男儿4 小时前
C# 类和继承(使用基类的引用)
java·javascript·c#
敢敢变成了憨憨8 小时前
java操作服务器文件(把解析过的文件迁移到历史文件夹地下)
java·服务器·python
苇柠8 小时前
Java补充(Java8新特性)(和IO都很重要)
java·开发语言·windows
Lin_XXiang8 小时前
java对接bacnet ip协议(跨网段方式)
java·物联网
白总Server8 小时前
C++语法架构解说
java·网络·c++·网络协议·架构·golang·scala
咖啡啡不加糖8 小时前
雪花算法:分布式ID生成的优雅解决方案
java·分布式·后端
小杜-coding9 小时前
天机学堂(初始项目)
java·linux·运维·服务器·spring boot·spring·spring cloud