使用一个线程安全队列、unsafe、LockSupport 实现的一个简单的Lock
代码如下:
import sun.misc.Unsafe;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;
/**
* AQS(AbstractQueuedSynchronizer)
* CAS(compare and swap)
*/
public class TulingLock {
// 当前加锁状态,记录加锁的次数
private volatile int state = 0;
// 当前持有锁的线程
private Thread lockHolder;
private ConcurrentLinkedQueue<Thread> waiters = new ConcurrentLinkedQueue<>();
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 boolean acquire() {
Thread current = Thread.currentThread();
// 初始状态
int c = getState();
if (0 == c) { // 同步器还没有被持有
if ((waiters.size() == 0 || current == waiters.peek()) && compareAndSwapState(0, 1)) {
setLockHolder(current);
return true;
}
}
return false;
}
/**
* 加锁
*/
public void lock() {
Thread current = Thread.currentThread();
// 加锁成功
if (acquire()) {
return;
}
waiters.add(current);
for (; ;) {
if ((current == waiters.peek()) && acquire()) {
waiters.poll();
return;
}
// 阻塞线程
LockSupport.park(current);
}
}
/**
* 解锁过程
*/
public void unlock() {
if (Thread.currentThread() != getLockHolder()) {
throw new RuntimeException("lockeholder is not current thread");
}
int state = getState();
if (compareAndSwapState(state, 0)) {
setLockHolder(null);
Thread headThread = waiters.peek();
if (headThread != null) {
LockSupport.unpark(headThread);
}
}
}
/**
* 原子操作
*/
public final boolean compareAndSwapState(int except, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, except, update);
}
private static final Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
private static final long stateOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset(TulingLock.class.getDeclaredField("state"));
} catch (Exception e) {
throw new Error();
}
}
}
获取unsafe实例代码:
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class UnsafeInstance {
public static Unsafe reflectGetUnsafe() {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
测试代码:
public class CurrentTest {
public static void main(String[] args) {
TulingLock zz = new TulingLock();
for (int i = 0; i < 100; i++) {
new Thread(() -> {
zz.lock();
System.out.println(Thread.currentThread().getName() + " acquire lock");
// try {
// TimeUnit.SECONDS.sleep(1);
// } catch (Exception e) {e.printStackTrace();}
System.out.println(Thread.currentThread().getName() + " release lock");
zz.unlock();
}, "thread-" + i).start();
}
}
}