import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;
import sun.misc.Unsafe;
public class MyLock {
private static Unsafe unsafe;
/**
* 当前加锁状态,记录加锁的次数
*/
private volatile int state = 0;
/**
* 当前持有锁的线程
*/
private Thread lockHolder;
static {
Field theUnsafe = null;
try {
theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
theUnsafe.setAccessible(true);
try {
unsafe = (Unsafe) theUnsafe.get(null);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private static final long stateOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset(MyLock.class.getDeclaredField("state"));
} catch (NoSuchFieldException e) {
throw new Error();
}
}
// 等待队列
private static ConcurrentLinkedQueue <Thread> queue = new ConcurrentLinkedQueue<>();
public static Unsafe getUnsafe() {
return unsafe;
}
public static void setUnsafe(Unsafe unsafe) {
MyLock.unsafe = unsafe;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public Thread getLockHolder() {
return lockHolder;
}
public void setLockHolder(Thread lockHolder) {
this.lockHolder = lockHolder;
}
public static long getStateOffset() {
return stateOffset;
}
public final boolean compareAndSwapState(int oldValue, int newValue) {
return unsafe.compareAndSwapInt(this, stateOffset, oldValue, newValue);
}
private boolean tryAquire() {
int state = getState();
if (state == 0) {
// 可以加
if ((queue.size() == 0 || queue.peek() == Thread.currentThread()) //为0和,判断是否是队列的头部。
&& compareAndSwapState(0, 1)) {
lockHolder = Thread.currentThread();
return true;
}
}
return false;
}
public void lock() {
// 获取锁,CAS
if (tryAquire()) {
return;
}
Thread current = Thread.currentThread();
queue.add(current);
// 停留在当前方法
while (true) {
// 队列头先获取
if (queue.peek() == current && tryAquire()) {
System.out.println("hold lock thread-name" + current.getName());
return;
}
// 阻塞线程
LockSupport.park(current);
}
// 锁释放后,再次获得
}
public void unlock() {
// 不合法的
if (queue.peek() != Thread.currentThread()) {
throw new RuntimeException();
}
Thread current = Thread.currentThread();
int state = getState();
if (compareAndSwapState(1, 0)) {
System.out.println("hold lock thread-name" + current.getName() + " 释放成功");
setLockHolder(null);
Thread headThread = queue.peek();
if (headThread != null) {
// 解开阻塞。
LockSupport.unpark(headThread);
}
}
}
}