package com.xiaofeizhu.initial.utils;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;
/**
* @author Tobu君
* @version v1.0
* @date 2021/2/28 13:32
* @description 基于CAS实现synchronize锁
*/
public class CustomerLock {
/**
* 当前加锁状态,记录加锁次数
*/
private volatile int state = 0;
/**
* 当前处有锁的线程
*/
private Thread lockHolder;
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;
}
private static Unsafe unsafe;
static {
try {
//通过反射方式获取Unsafe类
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
unsafe = (Unsafe) theUnsafeInstance.get(Unsafe.class);
} catch (Exception e) {
e.printStackTrace();
}
}
private static final long stateOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset(CustomerLock.class.getDeclaredField("state"));
} catch (Exception e) {
throw new Error();
}
}
/**
* 获取锁
*
* @return
*/
private boolean acquireLock() {
Thread t = Thread.currentThread();
int state = getState();
if (state == 0) {
//需要判断当前等待线程是否为空,或者当前线程是队列的队头线程
if ((threadConcurrentLinkedQueue.size() == 0 || t == threadConcurrentLinkedQueue.peek()) && compareAndSwapState(0, 1)) {
setLockHolder(t);
return true;
}
}
return false;
}
/**
* 定义一个安全的队列保存等待线程
*/
private ConcurrentLinkedQueue<Thread> threadConcurrentLinkedQueue = new ConcurrentLinkedQueue<>();
/**
* 加锁
*/
public void lock() {
//1.获取锁:CAS
if (acquireLock()) {
return;
}
//未获取锁的线程放入等待线程队列
Thread t = Thread.currentThread();
threadConcurrentLinkedQueue.add(t);
//2.未加锁成功线程存放队列并阻塞
for (; ; ) {
if (threadConcurrentLinkedQueue.peek() == t && acquireLock()) {
System.out.println("Thread-name:" + t.getName());
//将队列中队头元素移除
threadConcurrentLinkedQueue.poll();
return;
}
//阻塞线程
LockSupport.park(t);
}
//3.锁被释放后,再次获取锁
}
/**
* 释放锁
*/
public void unlock() {
Thread thread = Thread.currentThread();
//判断是否是当前持有锁线程来释放锁
if (thread != lockHolder) {
throw new RuntimeException("不是持有锁的线程,不可以释放锁");
}
int state = getState();
if (compareAndSwapState(state, 0)) {
System.out.println(String.format("Thread-name:%s,释放锁成功", thread.getName()));
setLockHolder(null);
//唤醒等待队列中的第一个等待线程
Thread head = threadConcurrentLinkedQueue.peek();
if (head != null) {
LockSupport.unpark(head);
}
}
}
/**
* 原子操作
*
* @param oldValue 线程工作内存当中的锁
* @param newValue 要替换的新值
* @return
*/
public final boolean compareAndSwapState(int oldValue, int newValue) {
return unsafe.compareAndSwapInt(this, stateOffset, oldValue, newValue);
}
}
单元测试:
package com.xiaofeizhu.initial;
import com.xiaofeizhu.initial.utils.CustomerLock;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @author Tobu君
* @version v1.0
* @date 2021/2/28 14:21
* @description 自定义同步锁测试
*/
@SpringBootTest
class AQSLockTest {
private static int productNum = 5;
private static CustomerLock customerLock = new CustomerLock();
/**
* 未加锁测试
*/
@Test
void unLockTest() {
for (int i = 0; i < 10; i++) {
new Thread(()->{
getProductUnlockMeThod();
}).start();
new Thread(()->{
getProductUnlockMeThod();
}).start();
}
}
/**
* 加锁测试
*/
@Test
void lockTest() {
for (int i = 0; i < 10; i++) {
new Thread(()->{
getProductLockMeThod();
}).start();
new Thread(()->{
getProductLockMeThod();
}).start();
}
}
/**
* 未加锁获取商品方法
*/
void getProductUnlockMeThod(){
Thread thread = Thread.currentThread();
if(productNum>0){
System.out.println(String.format("恭喜用户:%s,成功购买商品:%d",thread.getName(),productNum));
productNum--;
}else{
System.out.println(String.format("对不起,用户:%s,当前商品库存为0",thread.getName()));
}
}/**
* 加锁获取商品方法
*/
void getProductLockMeThod(){
Thread thread = Thread.currentThread();
customerLock.lock();
if(productNum>0){
System.out.println(String.format("恭喜用户:%s,成功购买商品:%d",thread.getName(),productNum));
productNum--;
}else{
System.out.println(String.format("对不起,用户:%s,当前商品库存为0",thread.getName()));
}
customerLock.unlock();
}
}