zoukankan      html  css  js  c++  java
  • 如何基于aqs实现一个锁

    AQS是java中并发的半壁江山,什么ReetrantLock、Condition、ReetrantReadWriteLock等,都是基于AQS实现。

    一、AQS使用方式以及设计模式

    AQS使用了模板模式,所谓的模板模式,通过一个例子来看-----以设计房子为例

    1、模板抽象类:HouseTemplate

    public abstract class HouseTemplate {
    
        protected HouseTemplate(String name){
            this.name = name;
        }
    
        protected String name;
    
        protected abstract void buildDoor();
    
        protected abstract void buildWindow();
    
        protected abstract void buildWall();
    
        protected abstract void buildBase();
    
        //公共逻辑
        public final void buildHouse(){
    
            buildBase();
            buildWall();
            buildDoor();
            buildWindow();
    
        }
    
    }

    2、子类1:HouseOne

    public class HouseOne extends HouseTemplate {
    
        HouseOne(String name){
            super(name);
        }
    
        @Override
        protected void buildDoor() {
            System.out.println(name +"的门要采用防盗门");
        }
    
        @Override
        protected void buildWindow() {
            System.out.println(name + "的窗户要面向北方");
        }
    
        @Override
        protected void buildWall() {
            System.out.println(name + "的墙使用大理石建造");
        }
    
        @Override
        protected void buildBase() {
            System.out.println(name + "的地基使用钢铁地基");
        }
        
    }

    3、子类2:HouseTwo

    public class HouseTwo extends HouseTemplate {
    
        HouseTwo(String name){
            super(name);
        }
    
        @Override
        protected void buildDoor() {
            System.out.println(name + "的门采用木门");
        }
    
        @Override
        protected void buildWindow() {
            System.out.println(name + "的窗户要向南");
        }
    
        @Override
        protected void buildWall() {
            System.out.println(name + "的墙使用玻璃制造");
        }
    
        @Override
        protected void buildBase() {
            System.out.println(name + "的地基使用花岗岩");
        }
    
    }

    4、测试类:Clienter

    public class Clienter {
    
        public static void main(String[] args){
            HouseTemplate houseOne = new HouseOne("房子1");
            HouseTemplate houseTwo = new HouseTwo("房子2");
            houseOne.buildHouse();
            houseTwo.buildHouse();
        }
    
    }

    运行结果:

    房子1的地基使用钢铁地基
    房子1的墙使用大理石建造
    房子1的门要采用防盗门
    房子1的窗户要面向北方
    房子2的地基使用花岗岩
    房子2的墙使用玻璃制造
    房子2的门采用木门
    房子2的窗户要向南
    
    
    房子1的地基使用钢铁地基
    房子1的墙使用大理石建造
    房子1的门要采用防盗门
    房子1的窗户要面向北方
    房子2的地基使用花岗岩
    房子2的墙使用玻璃制造
    房子2的门采用木门
    房子2的窗户要向南

    通过以上例子,我们认识了模板模式中的基本方法和模板方法,其中HouseTemplate中的buildHouse方法就是基本方法,其余四个均为模板方法。其中基本方法一般会用final修饰,保证其不会被子类修改,而模板方法则使用protected修饰,表明其需要在子类中实现。

    AQS也是基于这种模式来实现的,所以如果你要自己实现一个锁,就需要针对性的覆盖与实现AQS的某些方法。当然AQS这么强大,提供了独占式锁以及共享式锁的功能,你需要根据独占还是共享来选择实现哪些方法。

    独占式:

    1、获取

    tryAcquire

    accquire

    acquireInterruptibly

    tryAcquireNanos

    2、释放

    tryRelease

    release

    共享式:

    1、获取

    tryAcquireShared

    acquireShared

    acquireSharedInterruptibly

    tryAcquireSharedNanos

    2、释放

    tryReleaseShared

    releaseShared

    独占式、共享式都要实现的方法

    1、这个同步器是否处于独占模式  isHeldExclusively

    2、同步状态state:

      getState:获取当前的同步状态

      setState:设置当前同步状态

      compareAndSetState 使用CAS设置状态,保证状态设置的原子性

    二、基于AQS自实现的锁(独占式)

    package com.xiangxue.ch4.aqs;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.AbstractQueuedSynchronizer;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    
    /**
     *类说明:实现一个自己的类ReentrantLock
     */
    public class SelfLock implements Lock{
        
        //state 表示获取到锁 state=1 获取到了锁,state=0,表示这个锁当前没有线程拿到
        private static class Sync extends AbstractQueuedSynchronizer{
            
            //是否占用
            protected boolean isHeldExclusively() {
                return getState()==1;
            }
            
            //通过state维护当前是否有线程拿到锁,获取锁也就是通过CAS的方式将state从0设置为1,成功后将独占锁设置为自己
            protected boolean tryAcquire(int arg) {
                if(compareAndSetState(0,1)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
                return false;
            }
            
            //这地方不用使用CAS的原因是释放锁只有当前拿到锁的一个线程可以释放,所以不存在竞争条件
            protected boolean tryRelease(int arg) {
                if(getState()==0) {
                    throw new UnsupportedOperationException();
                }
                setExclusiveOwnerThread(null);
                setState(0);
                return true;
            }
            
            Condition newCondition() {
                return new ConditionObject();
            }
        }
        
        private final Sync sycn = new Sync();
    
        @Override
        public void lock() {
            sycn.acquire(1);
            
        }
    
        @Override
        public void lockInterruptibly() throws InterruptedException {
            sycn.acquireInterruptibly(1);
            
        }
    
        @Override
        public boolean tryLock() {
            return sycn.tryAcquire(1);
        }
    
        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return sycn.tryAcquireNanos(1, unit.toNanos(time));
        }
    
        @Override
        public void unlock() {
            sycn.release(1);
            
        }
    
        @Override
        public Condition newCondition() {
            return sycn.newCondition();
        }
    
    
    }

    三、基于AQS自实现的锁(共享式)

    package com.xiangxue.ch4.aqs;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.AbstractQueuedSynchronizer;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
    
    /**
     *类说明:自定义共享锁
     */
    public class TrinityLock   {
    
        //为3表示允许两个线程同时获得锁
        private final Sync sync = new Sync(3);
    
        private static final class Sync extends AbstractQueuedSynchronizer {
            
            Sync(int count) {
                if (count <= 0) {
                    throw new IllegalArgumentException("count must large than zero.");
                }
                setState(count);
            }
    
            public int tryAcquireShared(int reduceCount) {
                for (;;) {
                    int current = getState();
                    int newCount = current - reduceCount;
                    if (newCount < 0 || compareAndSetState(current, newCount)) {
                        return newCount;
                    }
                }
            }
    
            public boolean tryReleaseShared(int returnCount) {
                for (;;) {
                    int current = getState();
                    int newCount = current + returnCount;
                    if (compareAndSetState(current, newCount)) {
                        return true;
                    }
                }
            }
    
            final ConditionObject newCondition() {
                return new ConditionObject();
            }
        }
    
        public void lock() {
            sync.acquireShared(1);
        }
    
        public void unlock() {
            sync.releaseShared(1);
        }
    
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }
    
        public boolean tryLock() {
            return sync.tryAcquireShared(1) >= 0;
        }
    
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return sync.tryAcquireSharedNanos(1, unit.toNanos(time));
        }
    
        public Condition newCondition() {
            return sync.newCondition();
        }
    }

    简单来说,就是将state初始化>1,表示一共可以有多个线程占有,不过这种没有实现读跟写的分离。

  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1160 FatMouse's Speed
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1003 Max Sum
    HDU 1297 Children’s Queue
    UVA1584环状序列 Circular Sequence
    UVA442 矩阵链乘 Matrix Chain Multiplication
    DjangoModels修改后出现You are trying to add a non-nullable field 'download' to book without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:
    opencv做的简单播放器
    c++文件流输入输出
  • 原文地址:https://www.cnblogs.com/alimayun/p/12153034.html
Copyright © 2011-2022 走看看