4.4 AQS即AbstractQueuedSynchronizer 基本方法和通过AQS的实现自定义锁并使用测试

AQS使用方式和其中的设计模式

AQS使用了模板模式,定义了线程操作需要的基本末班,继承子类只需要按照这些模板去操作

AQS常用的模板方法名

方法名称描述
void acquire(int arg)

独占式获取同步状态,如果当前线程获取同步状态成功,则返回;

否则就会进入同步队列等待,该方法将会调用重写的tryAcquire(int arg)方法

void acquireInterruptibly(int arg)

与acquire(int arg)相同,但是该方法能够响应中断,当前线程为获取到同步状态

而进入同步队列中,如果当前线程被中断,则该方法会抛出InterruptedException并返回

boolean tryAcquireNanos(int arg,long nanos)在acquireInterruptibly(int arg)基础上增加了超时限制,如果当前线程在超时时间内没有获取到同步状态,那么就会返回发生了,如果获取到了就返回true
void acquireShared(int arg)共享式地获取同步状态,如果当前线程为获取到同步状态,将会进入同步队列等待,与独占式获取的主要区别是在同一个时刻,可以有多个线程获取到同步状态
void acquireSharedInterruptibly(int arg)与acquireShared(int arg)相同,该方法响应中断
boolean tryAcquireSharedNanos(int arg,long nanos)在void acquireSharedInterruptibly(int arg)基础上加上了超时限制
boolean release(int arg)独占式地释放同步状态,该方法会在释放同步状态之后,将同步队列中第一个节点包含的线程唤醒
boolean releaseShared(int arg)共享式地释放同步状态
Collection<Thread> getQueuedThreads()获取等待在同步队列上的线程集合

能够被重写的方法

方法名称描述
protected boolean tryAcquirek(int arg)

独占式获取同步状态,实现该方法需要查询当前状态并判断同步状态是否符合预期

然后在进行CAS设置同步状态

protected boolean tryRelease(int arg)独占式释放同步状态,等待获取同步状态的贤臣干将有机会获取到同步状态
protected int tryAcquireShared(int arg)共享式获取同步状态,返回大于等于0的值,表示获取成功,防止,获取失败
protected boolean tryReleaseShared(int arg)共享式释放同步状态
protected boolean isHeldExclusively()当前同步器是否在独占模式先被贤臣高占勇,一般发方法表示是否被当前线程锁独占

访问或者修改同步状态是,需要通过修改state的值来改变同步状态

getState()获取当前同步状态
setState(int newState)设置当前同步状态
compareAndSetState(int expect,int update)使用CAS设置当前状态,该方法能够保证状态设置的原子性

代码示例,实现自己的独占锁:通过参考ReentrentLock

1、实现loc接口

2、内部内继承AQS

注:自己手动写过之后,发现独占锁写起来还是比较简单的,实现所有lock的方法,内部类Syn编写释放和获取锁的方法,由于是独占锁,所以不用关心共享Share相关的方法,代码如下

public class MyLock implements Lock {
    class Syn extends AbstractQueuedSynchronizer{
        //尝试获取锁
        @Override
        protected boolean tryAcquire(int arg) {
            if(compareAndSetState(0,1)){
                //设置当前拥有独占访问的线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if(getState() == 0){
                throw new IllegalMonitorStateException();
            }else{
                setExclusiveOwnerThread(null);
                setState(0);
                return true;
            }
        }

        //因为是独占锁,所以shared方法就不用管了
        Condition newCondition(){return new ConditionObject();}
    }

    //新建一个操作的代理Syn
    Syn syn =  new Syn();
    @Override
    public void lock() {
        System.out.println(Thread.currentThread().getName()+":开始获取锁");
        syn.acquire(1);
        System.out.println(Thread.currentThread().getName()+":已经获取锁");

    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        syn.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return syn.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return syn.tryAcquireNanos(1,unit.toNanos(time));
    }

    @Override
    public void unlock() {
        System.out.println(Thread.currentThread().getName()+":准备释放锁");
        syn.release(1);
        System.out.println(Thread.currentThread().getName()+":释放锁完成");

    }

    @Override
    public Condition newCondition() {
        return syn.newCondition();
    }
}

使用自定义独占锁:使用方法和ReentrantLock相同,

public class Test {
    private static Lock lock = new MyLock();
    static class Customer extends Thread {
        @Override
        public void run() {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()+":开始执行任务,任务时间1秒");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 4; i++) {
            new Customer().start();
        }
    }
}

结果:启动四个线程,在每一个线程执行完之后,才能执行下一个线程

Thread-0:开始获取锁
Thread-2:开始获取锁
Thread-1:开始获取锁
Thread-0:已经获取锁
Thread-3:开始获取锁
Thread-0:开始执行任务,任务时间1秒
Thread-0:准备释放锁
Thread-0:释放锁完成
Thread-2:已经获取锁
Thread-2:开始执行任务,任务时间1秒
Thread-2:准备释放锁
Thread-2:释放锁完成
Thread-1:已经获取锁
Thread-1:开始执行任务,任务时间1秒
Thread-1:准备释放锁
Thread-1:释放锁完成
Thread-3:已经获取锁
Thread-3:开始执行任务,任务时间1秒
Thread-3:准备释放锁
Thread-3:释放锁完成

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值