1.AbstractQueuedSynchronizer(AQS)简单介绍
AQS定义了一套多线程访问共享资源的同步器框架,其核心功能都是围绕着其32位整型属性state进行,一般可以说它表示锁的数量,对同步状态的控制可以实现不同的同步工具,例如闭锁、信号量、栅栏等等。为了保证可见性此变量被声明为volatile,保证每次的原子更新都将及时反映到每条线程上。而对于同步状态的管理可以大体分为两块,一是独占模式的管理,另外是共享模式的管理
2.可重入锁简单实现
利用AQS实现Lock接口的方法
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
//使用AQS实现可重入锁
public class Mutex implements Lock{
private Sync sync = new Sync();
//借助AQS实现同步
private class Sync extends AbstractQueuedSynchronizer{
@Override
protected boolean tryAcquire(int arg) {
/***
* 返回true表示可以获取锁
*/
Thread current = Thread.currentThread();
/**
* state相当于信号量,作为锁的状态标识
*/
int state = getState();
if(state == 0){
if(compareAndSetState(0,arg)){
setExclusiveOwnerThread(current);
return true;
}
}else if(current == getExclusiveOwnerThread()){ //如果是相同线程则可重入
state += arg;
setState(state);
return true;
}
/**
* 返回false表示不能获取锁
*/
return false;
}
@Override
protected boolean tryRelease(int arg) {
/**
* 返回true表示可以释放锁
*/
if(Thread.currentThread()!=getExclusiveOwnerThread())
throw new RuntimeException();
int state = getState()-arg;
boolean flag = false;
if(state == 0){
setExclusiveOwnerThread(null);
flag = true;
}
/**
* 返回false表示不能释放锁
*/
setState(state); //更新重入锁状态
return flag;
}
/**
* 判断是否获取到了锁
*/
@Override
protected boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
}
//实现Lock接口的方法
@Override
public void lock() {
sync.acquire(1);//内部会先调用tryAcquire方法判断是否可以获取锁
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1,unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(1);//内部会先调用tryRelease方法判断是否可以释放锁
}
@Override
public Condition newCondition() {
return sync.new ConditionObject();
}
}
3.测试
public class Multi {
private int value = 0;
Mutex mutex = new Mutex(); //创建自定义锁对象
//ReentrantLock mutex = new ReentrantLock();
public void incA(){
mutex.lock(); //获取锁
value +=1;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A: "+value);
incB(); //可重入测试
mutex.unlock(); //释放锁
}
public void incB(){
mutex.lock(); //获取锁
value += 1;
System.out.println("B: "+value);
mutex.unlock(); //释放锁
}
@Test
public void test(){
Multi multi = new Multi();
//线程1
new Thread(new Runnable() {
@Override
public void run() {
for(;;){
multi.incA();
}
}
}).start();
//线程2
new Thread(new Runnable() {
@Override
public void run() {
for(;;){
multi.incA();
}
}
}).start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}