您现在的位置是:首页 > 文章详情

Java并发编程 -- AQS入门&实现可重入锁

日期:2018-06-12点击:442

Java并发编程 -- AQS可能会看的一脸懵逼,今天实战一个项目练手AQS

MyAQSLock.java

/** * Created by Fant.J. */ public class MyAQSLock implements Lock { private Helper helper = new Helper(); private class Helper extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int arg) { // 如果第一个线程进来,可以拿到锁,因此我们可以返回true // 如果第二个线程进来,则拿不到锁,返回false。有种特例,如果当前进来的线程和当前保存的线程是同一个线程,则可以拿到锁,但是有代价,要更新状态值 // 如何判断是第一个线程进来还是其他线程进来? //获取状态值 int state = getState(); Thread t = Thread.currentThread(); //如果状态=0,那就是第一个线程 if (state == 0) { if (compareAndSetState(0, arg)) { //设置当前线程为独占锁线程 setExclusiveOwnerThread(t); return true; } } else if (getExclusiveOwnerThread() == t) { setState(state + 1); return true; } return false; } @Override protected boolean tryRelease(int arg) { // 锁的获取和释放肯定是一一对应的,那么调用此方法的线程一定是当前线程 //获取当前线程,如果不等于独占锁的线程 if (Thread.currentThread() != getExclusiveOwnerThread()) { throw new RuntimeException(); } int state = getState() - arg; boolean flag = false; if (state == 0) { setExclusiveOwnerThread(null); flag = true; } setState(state); return flag; } Condition newCondition() { return new ConditionObject(); } } @Override public void lock() { helper.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { helper.acquireInterruptibly(1); } @Override public boolean tryLock() { return helper.tryAcquire(1); } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return helper.tryAcquireNanos(1, unit.toNanos(time)); } @Override public void unlock() { helper.release(1); } @Override public Condition newCondition() { return helper.newCondition(); } } 

从上往下分析,首先继承Lock接口,然后定义一个子类为非公共内部帮助器类Helper类,Helper类继承AQS,重写它的tryAcquire和tryRelease方法。作为锁的获取和释放。然后填充Lock的子类实现。(为什么Lock子类方法里传值都是1呢,因为AQS源码就是这样,1一路传到底),注释还算详细,就不在这多说了。

/** * Created by Fant.J. */ class TestAQS { private int value; private MyAQSLock myAQSLock = new MyAQSLock(); public int next(){ myAQSLock.lock(); try { Thread.sleep(300); return value++; } catch (InterruptedException e) { throw new RuntimeException(); }finally { myAQSLock.unlock(); } } public void a() { myAQSLock.lock(); System.out.println("a"); b(); myAQSLock.unlock(); } public void b() { myAQSLock.lock(); System.out.println("b"); myAQSLock.unlock(); } public static void main(String[] args) { TestAQS test = new TestAQS(); new Thread(new Runnable() { @Override public void run() { test.a(); } }).start(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(Thread.currentThread().getName()+" "+test.next()); } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(Thread.currentThread().getName()+" "+test.next()); } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(Thread.currentThread().getName()+" "+test.next()); } } }).start(); } } 

开了四个线程,一个线程去跑a方法,a方法中调用b方法,a、b方法调用之前都有加锁,之后有解锁,这个线程用来做可重入锁的测试,其他三个线程是测试线程安全。

结果图

img_72d3e977002631a21a4fc114db5c010e.png
原文链接:https://yq.aliyun.com/articles/650230
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章