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操作直到成功才退出循环

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值