我是靠谱客的博主 轻松小天鹅,最近开发中收集的这篇文章主要介绍Lock的基本使用及原理笔记,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述


java.util.concurrent 并发工具包


Lock
Lock是个接口,ReentrantLock唯一实现Lock的类
synchronized和ReentrantLock都支持重入锁

当多个线程争抢锁,其他的会阻塞

AQS同步工具
1、独占->互斥
2、共享->读写锁

AQS的基本实现
1、一个共享数据类记录锁的状态(有锁/无锁)
state:锁标记,0是无锁、大于0是有锁和重入次数,通过cas实现原子性(乐观锁)

Node节点信息

static final class Node {
        
        static final Node SHARED = new Node();
        
        static final Node EXCLUSIVE = null;

        static final int CANCELLED =  1;
       
        static final int SIGNAL    = -1;
        
        static final int CONDITION = -2;
        
        static final int PROPAGATE = -3;
       
        volatile int waitStatus;
        
        volatile Node prev;

        volatile Node next;
      
        volatile Thread thread;
        
        Node nextWaiter;

        final boolean isShared() {
            return nextWaiter == SHARED;
        }

      
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // Used to establish initial head or SHARED marker
        }

        Node(Thread thread, Node mode) {     // Used by addWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // Used by Condition
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

a、b、c线程执行lock()争抢锁流程(AQS)
1、a先执行lock.lock()获取到锁后获取到了,执行业务代码
2、b在执行lock.lock()没有抢到锁时会被包装成Node节点加入AQS队列并挂起,每个Node节点中会有一个pre指向上一个被挂起的Node和一个next指向下一个进来被挂起的Node,AQS队列中第一个Node节点中thread指向为空,表示获得所的线程,第二个Node才是线程b
3、c接着执行lock.lock()也没有抢到锁,然后被包装成Node,c的Node的pre会指向b的Node,b的Node的next会指向c的Node,这样多个Node就组成了一个双向链表
4、当a走完业务代码执行lock.unlock()释放了锁后,会移除第一个Node节点并唤起AQS队列中第二个Node也就是b并继续执行业务代码

lock.Condition
a、b线程执行lock()争抢锁,a在释放锁钱执行condition.await流程(AQS)
1、2同上
3、当a走业务代码执行condition.await后,会释放当前的锁并清空重入次数,然后被阻塞并加入到condition队列中,然后会移除第一个Node节点并唤起AQS队列中第二个Node也就是b并继续执行业务代码
4、b执行lock.lock抢到锁后执行完业务并执行condition.signal(),就会把condition队列中的第一个Node也就是A加入到AQS队列中去等待被唤醒重新争抢锁

CountDownLatch/CycliBarrier
Semaphore 限流

阻塞队列
通过ReencurrentLock和condition实现
ArrayBlockQueue
LinkBlockQueue
DelayQueue
SynchrousQueue


Atomic原子操作的原理
通过一个do-while循环不断去查询再CAS操作直到成功才退出循环

最后

以上就是轻松小天鹅为你收集整理的Lock的基本使用及原理笔记的全部内容,希望文章能够帮你解决Lock的基本使用及原理笔记所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部