利用AQS实现自定义锁,只需要自定义实现一个同步器,重写AQS中两个方法tryAcquire和tryRelease,如果是
共享锁的话则只需重写tryAcquireShared和tryReleaseShared两个方法,如果需要实现Condition效果则需要另外
重写isHeldExclusively方法。
这里只是简单的实现了自定义独占锁的效果,只提供了加锁和解锁两个方法。
package com.ywu.demo.thread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock implements Lock {
private Sync sync;
public MyLock() {
sync = new Sync();
}
@Override
public void lock() {
sync.acquire(1);
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + "尝试获取锁,状态为" + thread.getState());
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return null;
}
private class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
Thread thread = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && compareAndSetState(0, arg)) {
setExclusiveOwnerThread(thread);
System.out.println(Thread.currentThread().getName() + "获取到锁");
return true;
}
} else {
int state = c + arg;
if (getExclusiveOwnerThread() == thread) {
setState(state);
System.out.println(Thread.currentThread().getName() + "重入获取到锁");
return true;
}
}
System.out.println(Thread.currentThread().getName() + "尝试获取锁失败");
return false;
}
@Override
protected boolean tryRelease(int arg) {
int c = getState() - arg;
boolean free = false;
if (Thread.currentThread() != getExclusiveOwnerThread()) {
throw new IllegalMonitorStateException();
}
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
System.out.println(Thread.currentThread().getName() + "释放锁");
}
setState(c);
return free;
}
}
}
测试类
package com.ywu.demo.thread;
public class MyLockTest {
private static int count = 0;
public static void main(String[] args) {
testMyLock();
}
public static void testMyLock() {
MyLock myLock = new MyLock();
new Thread(() -> {
myLock.lock();
for (int i = 0; i < 100; i++) {
count += 1;
System.out.println(Thread.currentThread().getName() + ", count = " + count);
}
myLock.unlock();
}).start();
new Thread(() -> {
myLock.lock();
for (int i = 0; i < 100; i++) {
count += 1;
System.out.println(Thread.currentThread().getName() + ", count = " + count);
}
myLock.unlock();
}).start();
}
}