功能
具备基本的加锁、解锁功能,并且是非公平的(即允许插队)。
代码
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;
}
}
- 非公平性实现:
在 tryAcquire 方法中,直接尝试获取锁(通过 CAS 操作),不考虑等待队列中是否有其他线程在等待
这与公平锁的区别在于公平锁会先检查队列中是否有等待线程
- 可重入支持:
如果当前线程已经是锁的持有者,则增加 state 计数
释放锁时需要释放相同次数
- 状态管理:
state = 0 表示锁未被占用
state > 0 表示锁被占用,且数值表示重入次数
- 独占模式:
只允许一个线程持有锁
使用 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
}
}