并发----AQS

1 了解AQS

要求:可以画出AQS自旋锁的图且复述出整个过程java

AQS (AbstractQueuedSynchronizer)是一个帮助器,自定义锁的一个帮助器(体如今代码上 私有的内部类继承AQS)api

2 了解AQS的API

要求:经过java.util.concurrent.locks 下的 Lock和 AbstractQueuedSynchronizer的api了解AQS安全

Acquire()ide

尝试获取锁,若是没有获取到锁的画,就把当前节点放置到队列的末尾测试

3 可以经过AQS写一个锁

自定义锁ui

package src.main.concurrent.AQS;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * 自定义锁
 * 1 实现Lock
 * 2 AQS 私有内部类继承AQS
 * 3 重写tryAcquire/tryRelease
 * compareAndSetState   经过CAS方式修改值
 * setExclusiveOwnerThread  设置当前值占有资源
 *
 * 可重入锁,在MyLock基础之上修改  获取锁 释放锁部分逻辑
 *
 * @author liuhuxiang
 * @version $Id: MyLock.java, v 0.1 2018年10月09日 21:18 liuhuxiang Exp $
 */
public class MyLock implements Lock {

    private AQSHelper aQSHelper = new AQSHelper();

    // 这里就能够体现AQS是一个帮助类
    private class AQSHelper extends AbstractQueuedSynchronizer {

        //获取锁
        //注意这里的arg表示信号量,正常来讲arg为1
        @Override
        protected boolean tryAcquire(int arg) {

            //当前资源没有线程占用
            if (getState() == 0) {
                //经过CAS方式获取原子性的修改
                if (compareAndSetState(0, arg)) {
                    //设置当前值占有资源
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
          //可重入锁--获取锁修改 只要在AQS基础之上加上一个判断便可 }else if(getExclusiveOwnerThread()==Thread.currentThread()){ setState(getState()+arg); return true; }
            return false;
        }

        //释放锁
        @Override
        protected boolean tryRelease(int arg) {
            //减去信号量
            int state = getState() - arg;
            boolean flag = false;
            //判断释放后是否为0
            if (state == 0) {
                setExclusiveOwnerThread(null);
                setState(state);
                return true;
            }
            //存在线程安全吗?重入性的问题,当前已经独占了资源()state,因此这里不存在安全问题
           //可重入锁--释放锁修改 这里不要作任何修改,等于获取锁加了两边arg,释放锁减掉两边arg
            setState(state);
            return false;
        }

        //这里参考jdk
        public Condition newConditionObject() {
            return new ConditionObject();
        }

    }

    @Override
    public void lock() {
        aQSHelper.acquire(1);
    }

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

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

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        //试图以独占模式获取对象,若是被中断则停止,若是到了给定超时时间,则会失败。

        return aQSHelper.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        aQSHelper.release(1);
    }

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

使用自定义锁spa

package src.main.concurrent.AQS;

/**
 * 测试MyLock
 * 建立20个线程,每一个线程调用++方法,验证加锁不加锁两种方式
 *
 * @author liuhuxiang
 * @version $Id: TestMyLock.java, v 0.1 2018年10月09日 21:37 liuhuxiang Exp $
 */
public class TestMyLock {

    private int m = 0;

    MyLock myLock = new MyLock();

    private int increase() {
        myLock.lock();
        try {
            return m++;
        } finally {
            //确保最终释放锁
            myLock.unlock();
        }
    }

    public static void main(String[] args) {
        TestMyLock testMyLock = new TestMyLock();
        Thread[] threads = new Thread[20];
        for (int i = 0; i < 20; i++) {
            threads[i] = new Thread(() -> {
                System.out.println(testMyLock.increase());
            });
            threads[i].start();
        }

    }

}

探讨可重入锁线程

package src.main.concurrent.AQS;

/**
 * 探讨重入性问题
 * 调用的时候,发现只打印了a ,为何只打印了a,由于a()方法占用了锁,资源不为0了,因此b没法暂用资源
 *
 * 因此要去修改MyLock,多加一个可重入性的判断
 *
 * 可重入性:同一个锁多同一资源进行占有的时候,直接分配给这个线程
 *
 * @author liuhuxiang
 * @version $Id: TestMyLock2.java, v 0.1 2018年10月09日 21:46 liuhuxiang Exp $
 */
public class TestMyLock2 {

    private int m = 0;

    MyLock myLock = new MyLock();

    public void a() {
        myLock.lock();
        System.out.println("a");
        b();
        myLock.unlock();
    }

    public void b() {
        myLock.lock();
        System.out.println("b");
        myLock.unlock();

    }

    public static void main(String[] args) {
        TestMyLock2 testMyLock2 = new TestMyLock2();

        new Thread(() -> {
            testMyLock2.a();
        }).start();

    }

}
相关文章
相关标签/搜索