博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
并发----AQS
阅读量:6840 次
发布时间:2019-06-26

本文共 4424 字,大约阅读时间需要 14 分钟。

hot3.png

1 了解AQS

要求:能够画出AQS自旋锁的图且复述出整个过程

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

c41dc293b3707ab9587a621053c0d535f84.jpg

2 了解AQS的API

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

ab19e00372e2b36602d82c5fd8948150947.jpg

Acquire()

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

adb59cc7eb4c4f6df87688b73171f56c10b.jpg

7ca98d2d3a5861e334d9b2f989785ff35bd.jpg

3 能够通过AQS写一个锁

自定义锁

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

使用自定义锁

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

转载于:https://my.oschina.net/u/3523594/blog/2236923

你可能感兴趣的文章
git常用操作命令
查看>>
sendmail邮件服务器支持账户名大小写
查看>>
深入浅出WPF开发下载
查看>>
我的友情链接
查看>>
Putty添加SSH Key
查看>>
zuoye
查看>>
Oracle RAC 添加删除节点
查看>>
OU/Group/Group Policy组织单元、组和组策略
查看>>
菜鸟的DUBBO进击之路(二):Dubbo初识
查看>>
浏览器跑分测试
查看>>
Android的Activity屏幕切换动画(一)-左右滑动切换
查看>>
LVS+keeplived+nginx+tomcat高可用、高性能jsp集群
查看>>
Linux下清理内存和Cache方法
查看>>
XML1.1
查看>>
rhel6.3挂载HP-EVA6400磁阵--linux端操作流程
查看>>
Gradle构建脚本概要之构建块
查看>>
HashTable已经被淘汰了,不要在代码中再使用它
查看>>
ACCP学习旅程之----- 使用HTML语言开发商业站点(第一章 HTML的基本标签)
查看>>
AAD Connect 微软官方的描述准确吗?
查看>>
C++实现快速排序
查看>>