前言
昨天的面试,让我知道了阅读源码的重要性,今天就手写三种简单Lock来进行JUC的巩固。
代码实现
1、简单的Lock
package com.coolstar.locks;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock1 implements Lock {
private boolean isLock = false;
@Override
public synchronized void lock() {
while(isLock) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLock = true;
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public synchronized void unlock() {
isLock = false;
notify();
}
@Override
public Condition newCondition() {
return null;
}
}
对Lock接口进行实现,并且简单实现它的Lock和unLock方法。
2、可重入锁Lock
package com.coolstar.locks;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock2 implements Lock {
private boolean isLock =false;
private Thread lockBy = null;
private int lockCount = 0;
@Override
public synchronized void lock() {
Thread currentThread = Thread.currentThread();
while (isLock && lockBy != currentThread) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLock = true;
lockBy = currentThread;
lockCount++;
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public synchronized void unlock() {
isLock = false;
if (lockBy == Thread.currentThread()) {
lockCount--;
if (lockCount == 0) {
notify();
isLock = false;
lockBy = null;
}
}
}
@Override
public Condition newCondition() {
return null;
}
}
我们在第一种的基础上增加了可重入锁的机制。当获取锁的线程是当前线程时,进行可重入,lockCount自增。
3、基于AQS的Lock
package com.coolstar.locks;
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 MyLock3 implements Lock {
private class Helper extends AbstractQueuedSynchronizer {
//1.获取状态
//2.拿到状态,CAS判断(双重检测),并设置为独占锁
//3.判断是不是当前线程,要是当前线程的话就可重入
@Override
protected boolean tryAcquire(int arg) {
Thread t = Thread.currentThread();
int state = getState();
//说明无锁,就进行CAS进行取,若成功就设置为独占锁
if (state == 0) {
if (compareAndSetState(0,arg)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
//如果当前线程已经拿到锁,那就state+1进行重入
}else if (t == getExclusiveOwnerThread()) {
setState(state+1);
return true;
}
return false;
}
//1.先看是不是当前线程,如果不是,就不能释放,抛出异常
//2.如果是的话,判断state,如果state-1(arg) = 0,那就释放
@Override
protected boolean tryRelease(int arg) {
//锁的获取和释放需要一一对应,那么调用这个方法的线程,一定是当前线程
if (Thread.currentThread() != getExclusiveOwnerThread()) {
throw new RuntimeException();
}
int state = getState() - arg;
setState(state);
//如果state为0,说明独占锁被取消了
if(state == 0) {
setExclusiveOwnerThread(null);
return true;
}
return false;
}
//ConditionObject不能在外部使用,是AQS里面的
public Condition newCondition() {
return new ConditionObject();
}
}
Helper helper = new Helper();
@Override
public void lock() {
helper.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@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();
}
}
我们定义一个内部类实现AQS接口,再通过AQS实现锁。