JUC包的简单分析

JUC

通常所说的并发包(JUC)也就是 java.util.concurrent 及其子包,集中了 Java 并发的各种基础工具类,具体主要包括几个方面: 

  • 提供了 CountDownLatch、CyclicBarrier、Semaphore 等工具类,实现很多线程之间协作比 Synchronized 更加高级,可以实现更加丰富多线程操作的同步结构。
  • 提供了 ConcurrentHashMap、有序的 ConcunrrentSkipListMap,或者通过类似快照机制实现线程安全的动态数组 CopyOnWriteArrayList 等,各种线程安全的容器。 
  • 提供了 ArrayBlockingQueue、SynchorousQueue 或针对特定场景的 PriorityBlockingQueue 等,各种并发队列实现。
  • 强大的 Executor 框架,可以创建各种不同类型的线程池,调度任务运行等
  • 原子类
  • 锁接口

Lock接口

ReentranLock

继承接口Lock,除了能完 成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等 避免多线程死锁的方法

Lock接口主要方法

  • void lock(): 执行此方法时, 如果锁处于空闲状态, 当前线程将获取到锁. 相反, 如果锁已经 被其他线程持有, 将禁用当前线程, 直到当前线程获取到锁.
  • boolean tryLock():如果锁可用, 则获取锁, 并立即返回 true, 否则返回 false. 该方法和 lock()的区别在于, tryLock()只是"试图"获取锁, 如果锁不可用, 不会导致当前线程被禁用, 当前线程仍然继续往下执行代码. 而 lock()方法则是一定要获取到锁, 如果锁不可用, 就一 直等待, 在未获得锁之前,当前线程并不继续向下执行.
  • void unlock():执行此方法时, 当前线程将释放持有的锁. 锁只能由持有者释放, 如果线程 并不持有锁, 却执行该方法, 可能导致异常的发生.
  • Condition newCondition():条件对象,获取等待通知组件。该组件和当前的锁绑定, 当前线程只有获取了锁,才能调用该组件的 await()方法,而调用后,当前线程将缩放锁。
  • getHoldCount() :查询当前线程保持此锁的次数,也就是执行此线程执行lock方法的次 数。
  • getQueueLength():返回正等待获取此锁的线程估计数,比如启动 10 个线程,1 个 线程获得锁,此时返回的是9
  • getWaitQueueLength:(Condition condition)返回等待与此锁相关的给定条件的线 程估计数。比如 10 个线程,用同一个 condition 对象,并且此时这 10 个线程都执行了 condition对象的 await方法,那么此时执行此方法返回10
  • hasWaiters(Condition condition):查询是否有线程等待与此锁有关的给定条件 (condition),对于指定contidion对象,有多少线程执行了condition.await方法
  • hasQueuedThread(Thread thread):查询给定线程是否等待获取此锁
  • hasQueuedThreads():是否有线程等待此锁
  • isFair():该锁是否公平锁
  • isHeldByCurrentThread(): 当前线程是否保持锁锁定,线程的执行 lock 方法的前后分 别是false和true
  • isLock():此锁是否有任意线程占用
  • lockInterruptibly():如果当前线程未被中断,获取锁
  • tryLock():尝试获得锁,仅在调用时锁未被线程占用,获得锁
  • tryLock(long timeout TimeUnit unit):如果锁在给定等待时间内没有被另一个线程保持, 则获取该锁。 

实现可重入性

ReentrantLock 内部自定义了同步器 Sync(Sync 既实现了 AQS,又实现了 AOS,而 AOS 提供了一种互斥锁持有的方式),其实就是加锁的时候通过 CAS 算法,将线程对象放到一个双向链表中,每次获取锁的时候,看下当前维护的那个线程 ID 和当前请求的线程 ID 是否一样,一样就可重入

ReentrantLock中的公平锁和非公平锁的主要区别

公平锁中, 线程严格按照先进先出(FIFO)的顺序, 获取锁资源

非公平锁中, 拥有锁的线程在释放锁资源的时候, 当前尝试获取锁资源的线程可以和等待队列中的第一个线程竞争锁资源, 这就是ReentrantLcok中非公平锁的含义; 但是已经进入等待队列的线程, 依然是按照先进先出的顺序获取锁资源

ReadWriteLock 

读写锁基于的原理是多个读操作不需要互斥,如果读锁试图锁定时,写
锁是被某个线程持有,读锁将无法获得,而只好等待对方操作结束,这
样就可以自动保证不会读取到有争议的数据

StampedLock

在提供类似读写锁的同时,
还支持优化读模式。优化读基于假设,大多数情况下读操作并不会和写
操作冲突,其逻辑是先试着修改,然后通过 validate 方法确认是否进
入了写模式,如果没有进入,就成功避免了开销;如果进入,则尝试获
取读锁。 

Tools

如何让 Java 的线程彼此同步

JUC 中的同步器三个主要的成员:CountDownLatch、CyclicBarrier 和 Semaphore,通过它们可以方便地实现很多线程之间协作的功能

  • 三大同步器

          1.CountDownLatch

                

       2. CyclicBarrier

       3. Semaphore

                          

          CountDownLatch和CyclicBarrier区别:
         1.countDownLatch是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次
         2.CyclicBarrier的计数器更像一个阀门,需要所有线程都到达,然后继续执行,计数器递增,提供reset功能,可以多次使用

  • 一个条件辅助Condition

CountDownLatch、CyclicBarrier、Semaphore

CountDownLatch 

倒计数,允许一个或多个线程等待某些操作完成

CyclicBarrier

叫循环栅栏,它实现让一组线程等待至某个状态之后再全部同时执行,而且当所有等待线程被释放后,CyclicBarrier 可以被重复使用。CyclicBarrier 的典型应用场景是用来等待并发线程结束。 CyclicBarrier 的主要方法是 await(),await() 每被调用一次,计数便会减少 1,并阻塞住当前线程。当计数减至 0 时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。 在这之后,如果再次调用 await(),计数就又会变成 N-1,新一轮重新开始,这便是 Cyclic 的含义所在。CyclicBarrier.await() 带有返回值,用来表示当前线程是第几个到达这个 Barrier 的线程 

Semaphore

       Java 版本的信号量实现,用于控制同时访问的线程个数,来达到限制通用资源访问的目的,其原理是通过 acquire() 获取一
个许可,如果没有就等待,而 release() 释放一个许可。

       Semaphore 基本能完成 ReentrantLock 的所有工作,使用方法也与之类似,通过 acquire()与 release()方法来获得和释放临界资源。经实测,Semaphone.acquire()方法默认为可响应中断锁, 与 ReentrantLock.lockInterruptibly()作用效果一致,也就是说在等待临界资源的过程中可以被 Thread.interrupt()方法中断。 

      此外,Semaphore也实现了可轮询的锁请求与定时锁的功能,除了方法名tryAcquire 与tryLock 不同,其使用方法与ReentrantLock几乎一致。Semaphore也提供了公平与非公平锁的机制,也 可在构造函数中进行设定。 
Semaphore的锁释放操作也由手动进行,因此与ReentrantLock一样,为避免线程因抛出异常而 无法正常释放锁的情况发生,释放锁的操作也必须在finally代码块中完成。 

// 创建一个计数阈值为5的信号量对象 
  // 只能5个线程同时访问 
  Semaphore semp = new Semaphore(5); 
  try { // 申请许可 
   semp.acquire(); 
   try { 
    // 业务逻辑 
} catch (Exception e) { 
   } finally { 
    // 释放许可 
    semp.release(); 
   } 
  } catch (InterruptedException e) { 
  } 

AtomicInteger

Collections

 

Executor 之线程池

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值