使用AQS实现一个简单的可重入锁


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();
        }
    }
}

文章作者: Bryson
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bryson !
评论
 上一篇
下一篇 
  目录