美文网首页
java多线程(四)显示锁和AQS

java多线程(四)显示锁和AQS

作者: 7ColorLotus | 来源:发表于2020-05-23 23:52 被阅读0次
    • 常用的显示锁,基本上都是实现Lock接口,Lock接口常用的方法:
      lock() 获取锁
      unlock() 释放锁
      tryLock() 尝试获取锁
    • 使用显示锁的范式:
     try{
        lock.lock();
     }finally{
      lock.unlock();
    }
    
    • lock和synchronized的比较
      1. synchronized代码简洁
      2. Lock 可以中断,尝试获取,超时获取
      3. 尽量使用Synchronized,Synchronized默认实现了可重复锁。
      4. 可重复锁的概念:若一个程序或子程序可以“在任意时刻被中断然后操作系统调度执行另外一段代码,这段代码又调用了该子程序不会出错”,则称其为可重入(reentrant或re-entrant)的。
      5. 在Java内部,同一个线程调用自己类中其他synchronized方法/块时不会阻碍该线程的执行,同一个线程对同一个对象锁是可重入的,同一个线程可以获取同一把锁多次,也就是可以多次重入。原因是Java中线程获得对象锁的操作是以线程为单位的,而不是以调用为单位的。
      6. synchronized可重入锁的实现
        每个锁关联一个线程持有者和一个计数器。当计数器为0时表示该锁没有被任何线程持有,那么任何线程都都可能获得该锁而调用相应方法。 当一个线程请求成功后,JVM会记下持有锁的线程,并将计数器计为1。此时其他线程请求该锁,则必须等待。而该持有锁的线程如果再次请求这个锁, 就可以再次拿到这个锁,同时计数器会递增。当线程退出一个synchronized方法/块时,计数器会递减,如果计数器为0则释放该锁。
    • 公平锁和非公平锁(ReentrantLock实例化的时候指定,默认是非公平锁)
      1. 如果在时间上,先对锁进行获取的请求,一定先被满足,这就是公平的,反之就是非公平的
      2. 非公平锁的效率一般来说更高,比如前一个线程挂起,后一个线程无法请求到锁
    • ReadWriteLock和ReentrantReadWriteLock
      1. ReentrantLock和synchronized都是排他锁或者说独占锁,同一个时刻只允许一个线程拥有锁
      2. ReadWriteLock同一时刻允许多个读线程同时访问,但是写线程访问的时候,所有的读和写都被阻塞。即write是独占锁,read是共享锁
      3. 适用于读多写少的情况
    • Condition:通过lock.newCondition创建对象
      1. await():等待。将线程从同步队列转移到等待队列中
      2. signal():放开,将线程从等待队列转移到同步队列中。尽量使用signal,不要使用signalAll(),因为锁只能被一个线程拿到。
      3. 一个Lock可以对应多个Condition
    • LockSupport工具
      1. 作用: 构建同步组件的基础工具
      2. park:阻塞一个线程
      3. unpark:唤醒一个线程
    • AbstractQueuedSynchronizer深入分析
      1. 什么是AQS?学习它的必要性
      2. AQS使用方式和其中的设计模式:模板方法设计模式
        1)模板方法
            //独占式获取锁
            acquire(int arg)
            acquireInterruptibly(int arg)
            tryAcquireNanos(int arg, long nanosTimeout
            
            // 共享式获取锁
            acquireShared(int arg)
            acquireSharedInterruptibly(int arg)
            tryAcquireSharedNanos(int arg, long nanosTimeout)
            
            // 独占式释放锁
            release(int arg)
            
            //共享式释放锁
            releaseShared(int arg)
        
        2)需要子类覆盖的流程方法
            // 独占式尝试获取
            tryAcquire
            // 独占式释放
            tryRelease
            
            // 共享式获取
            tryAcquireShared
            // 共享式释放
            tryReleaseShared
            // 这个同步器是否占用
            isHeldExclusively()
        
        3)同步状态state:
            getState:获取当前的同步状态
            setState:设置当前的同步状态
            compareAndSetState:使用CAS设置状态,保证状态设置的原子性
        
      3. AQS中的数据结构-节点和同步队列
        Node:封装并发线程的类
        CANCELLED:线程等待超时或者中断了,节点被移除
        SIGNAL:后续的节点等待状态,当前节点,通知后面的节点去运行
        CONDITION: 当前节点处于等待队列
        PROPAGATE:传播
        0表示当前节点初始状态

    相关文章

      网友评论

          本文标题:java多线程(四)显示锁和AQS

          本文链接:https://www.haomeiwen.com/subject/lnwrahtx.html