java.util.concurrent.locks

image.png

Lock

image.png

实现类:

  1. **ReentrantLock**:可重入锁(常用)
  2. ReentrantReadWriteLock.**ReadLock** :读锁
  3. ReentrantReadWriteLock.**WriteLock** :写锁

    使用

    ```java Lock lock = new ReentrantLock(); // 默认非公平锁

// 加锁 lock.lock(); try { // 执行同步代码 } finally { // 解锁 lock.unlock(); }

  1. <a name="Rn4XC"></a>
  2. ### 默认锁
  3. ReentrantLock 默认无参构造函数创建的是非公平锁,公平锁可以传递一个值为 true 的布尔值创建。
  4. - 公平锁:非常公平,不能插队,必须先来后到,先来先执行;
  5. - 非公平锁:非常不公平,可以插队(默认是非公平锁);
  6. <a name="B0yHW"></a>
  7. ### Lock 与 Synchronized 的区别
  8. <a name="O93Tg"></a>
  9. ## Condition
  10. 当使用 Lock 替换 synchronized 方法和语句使用时,可以使用 Condition 取代了对象监视器方法使用,使用 Condition.await() 方法和 Condition.signalAll() 方法替代 Object.wait() 和 Object.notifyall()。
  11. <a name="H319s"></a>
  12. ### 通知唤醒-与 synchronized 对比
  13. **synchronized**
  14. ```java
  15. public synchronized void increment() {
  16. while (number != 0) {
  17. // 等待, 同步方法锁的是当前实例对象
  18. try {
  19. this.wait();
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. number += 1;
  25. System.out.println(Thread.currentThread().getName() + "=>" + number);
  26. this.notifyAll();
  27. }

Lock

final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();

public void increment() {
    try {
        lock.lock();
        while (number != 0) {
            // 等待, 同步方法锁的是当前实例对象
            try {
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        number += 1;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        condition.signalAll();
    } finally {
        lock.unlock();
    }
}

精准通知与唤醒

可以创建多个 Condition 对象代表不同情况,signal() 方法精准唤醒。

final Lock lock = new ReentrantLock();
final Condition conditionA = lock.newCondition();
final Condition conditionB = lock.newCondition();
/**
     * number = 1 A 执行
     * number = 2 B 执行
     */
private int number = 1;

public void printA() {
    try {
        lock.lock();
        while (number != 1) {
            // A 等待
            conditionA.await();
        }
        System.out.println(Thread.currentThread().getName() + " -> A");
        number = 2;
        // 唤醒 B 执行
        conditionB.signal();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

ReadWriteLock

实现类

实现类:ReentrantReadWriteLock,可以细粒度的划分为读锁 readLock、写锁 writeLock。其中读锁可以有多个线程同时进行,写锁只允许一个线程进入执行。

方法

  1. Lock readLock():读锁
  2. Lock writeLock():写锁

可以看出,读锁写锁也是属于 Lock 接口的,用法和 Lock 相同。

AbstractQueuedSynchronizer —— AQS

AQS 是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 ReentrantLock,Semaphore,其他的诸如 ReentrantReadWriteLock,SynchronousQueue,FutureTask 等等皆是基于 AQS 的。当然,我们自己也能利用 AQS 非常轻松容易地构造出符合我们自己需求的同步器。

AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是用 CLH 队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

CLH(Craig,Landin,and Hagersten) 队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS 是将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点(Node)来实现锁的分配。

locks、atomic - 图3

java.util.concurrent.atomic

image.png
Java 从 JDK1.5 开始提供了 java.util.concurrent.atomic 包(简称 atomic 包),这个包中的原子操作类提供了一种用法简单,性能高效,线程安全地更新一个变量的方式。
用法举例:

  1. public AtomicInteger():初始化一个默认值为0的原子型Integer
  2. public AtomicInteger(int initialValue):初始化一个指定值的原子型Integer
  3. int get():获取值
  4. int getAndIncrement():以原子方式将当前值加1,注意,这里返回的是自增前的值。
  5. int incrementAndGet():以原子方式将当前值加1,注意,这里返回的是自增后的值。
  6. int addAndGet(int data):以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果。
  7. int getAndSet(int value):以原子方式设置为newValue的值,并返回旧值。

    基本类型

    使用原子的方式更新基本类型
  • AtomicInteger:整形原子类
  • AtomicLong:长整型原子类
  • AtomicBoolean:布尔型原子类

    数组类型

    使用原子的方式更新数组里的某个元素

  • AtomicIntegerArray:整形数组原子类

  • AtomicLongArray:长整形数组原子类
  • AtomicReferenceArray:引用类型数组原子类

    引用类型

  • AtomicReference:引用类型原子类

  • AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
  • AtomicMarkableReference :原子更新带有标记位的引用类型

    对象的属性修改类型

  • AtomicIntegerFieldUpdater:原子更新整形字段的更新器

  • AtomicLongFieldUpdater:原子更新长整形字段的更新器
  • AtomicReferenceFieldUpdater:原子更新引用类型字段的更新器