一、创建MyLock
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 Helper helper = new Helper();
@Override
public void lock() {
helper.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
helper.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return helper.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return helper.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
helper.release(1);
}
@Override
public Condition newCondition() {
return helper.newCondition();
}
private class Helper extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
//如果第一个线程进来,可以拿到锁,返回true
//如果第二个线程进来,拿不到锁,返回false,有种特例,如果当前进来的线程和当前保存的线程是同一个线程,则可以拿到锁,但是要更新状态值
//如何判断是第一个线程进来还是其他线程进来
int state = getState();
Thread t = Thread.currentThread();
if (state == 0) {//判断是否是第一个线程
if (compareAndSetState(0, arg)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
} else if(getExclusiveOwnerThread() == t) {//判断当前进来的线程和当前保存的线程是否是同一个线程,实现重入锁,因为锁的是对象,所以只要是同一个Helper对象线程就是同一个线程
setState(state + 1);
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
//锁的获取和释放肯是一一对应的,那么调用此方法的线程一定是当前线程
if (Thread.currentThread() != getExclusiveOwnerThread()) {
throw new RuntimeException();
}
int state = getState() - arg;
setState(state);
if (state == 0) {
setExclusiveOwnerThread(null);
return true;
}
return false;
}
protected ConditionObject newCondition() {
return new ConditionObject();
}
}
}
二、编写测试代码
public class TestMyLock {
private int value;
private MyLock myLock = new MyLock();
public int getValue() {
myLock.lock();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
value ++;
myLock.unlock();
return value;
}
public void a() {
myLock.lock();
System.out.println("a");
b();
myLock.unlock();
}
public void b() {
myLock.lock();
System.out.println("b");
myLock.unlock();
}
public static void main(String[] args) {
TestMyLock testMyLock = new TestMyLock();
//检测是否会并发
Runnable runnable = () -> {
for (int i = 0; i<100; i++) {
System.out.println(Thread.currentThread().getId()+",值:" + testMyLock.getValue());
}
};
new Thread(runnable).start();
new Thread(runnable).start();
new Thread(runnable).start();
//检测重入锁
Runnable runnable1 = () -> testMyLock.a();
new Thread(runnable1).start();
}
}