秋招之路9:juc并发

j.u.c是java.util.concurrent的简称

通过查api,了解到是由以下这三个组成的。

juc包图

锁的两种实现方式

java并发编程,关于锁的实现方式有两种:

1.基于synchronized关键字实现同步,jvm内置锁,也叫隐式锁,由jvm自动加锁和解锁
2.juc下的lock接口实现的更加灵活的锁的实现方式,也叫显示锁,需要手动加锁和解锁

重要分类

locks部分:显示锁(互斥锁和读写锁)相关;
atomic部分:原子变量类相关,是构建非阻塞队列算法的基础,使用CAS实现;
executor部分:线程池相关;
collections部分:并发容器相关;
tools部分:同步工具相关,如信号量,闭锁,栅栏等;

lock图

ReentrantLock锁

ReentrantLock,可重入锁,是一种递归无阻塞的同步机制。
它可以等同于 synchronized的使用,但是 ReentrantLock 提供了比synchronized 更强大、灵活的锁机制,可以减少死锁发生的概率。
其中ReentrantLock里面涉及的公平锁与非公平锁;重入锁和非可重入锁。围绕着去实现的核心内在原理就是AQS抽象队列同步器。
里面ReentrantLock里面的变量

head 队列头
tail 队列尾
state 计数上锁次数
exlusiveOwnerThread 当前占有的线程
  • ReentrantLock 实现 Lock 接口,基于内部的 Sync 实现(Sync是ReentrantLock的一个内部类)。
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {};
public ReentrantLock() {
    sync = new NonfairSync();
}
  • Sync 实现 AQS ,提供了 FairSync 和 NonFairSync 两种实现(NonfairSync和FairSync 的两个子类)。
static final class NonfairSync extends Sync {};
static final class FairSync extends Sync {};

condition

Condition 和 Lock 一起使用以实现等待/通知模式,通过 await()和singnal() 来阻塞和唤醒线程。
传送门

//一个条件队列的典型例子
while(!conditionPredition)
    lock.wait();
doSomething();

Condition 是一种广义上的条件队列。
他为线程提供了一种更为灵活的等待 / 通知模式,线程在调用 await 方法后执行挂起操作,直到线程等待的某个条件为真时才会被唤醒。
Condition 必须要配合 Lock 一起使用,因为对共享状态变量的访问发生在多线程环境下。
一个 Condition 的实例必须与一个 Lock 绑定, Condition 一般是 Lock 的内部实现。

ReentrantReadWriteLock

读写锁维护着一对锁,一个读锁和一个写锁
通过分离读锁和写锁,使得并发性比一般的排他锁有了较大的提升:

1.在同一时间,可以允许多个读线程同时访问。
2.但是,在写线程访问时,所有读线程和写线程都会被阻塞。

特性:

  1. 公平性:支持公平性和非公平性。
  2. 重入性:支持重入。读写锁最多支持 65535 个递归写入锁和 65535 个递归读取锁。
  3. 锁降级:遵循获取写锁,再获取读锁,最后释放写锁的次序,如此写锁能够降级成为读锁。
    ReentrantReadWriteLock 实现 ReadWriteLock 接口,可重入的读写锁实现类。
public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    /** Inner class providing readlock */
    private final ReentrantReadWriteLock.ReadLock readerLock;
    /** Inner class providing writelock */
    private final ReentrantReadWriteLock.WriteLock writerLock;

在同步状态上,为了表示两把锁,将一个 32 位整型分为高 16 位和低 16 位,分别表示读和写的状态

         /*
         * Read vs write count extraction constants and functions.
         * Lock state is logically divided into two unsigned shorts:
         * The lower one representing the exclusive (writer) lock hold count,
         * and the upper the shared (reader) hold count.
         */

        static final int SHARED_SHIFT   = 16;
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        /** Returns the number of shared holds represented in count  */
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }

猜你喜欢

转载自www.cnblogs.com/whyaza/p/12348215.html