Marvel-Site Marvel-Site
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)

Marvel

吾必当乘此羽葆盖车
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)
  • Java

    • Java基础

    • Java进阶

    • Java容器

    • Java并发编程

      • 并发编程基本概念
      • 多线程
      • 创建多线程的方法
      • 比较与交换CAS
      • Java对象头与Monitor监视器
      • Java主流锁
      • synchronized关键字
      • volatile关键字
      • 线程池
      • 原子类Atomic
      • LockSupport工具
        • LockSupport介绍
        • 三种让线程等待和唤醒的方法?
      • 抽象队列同步器AQS
      • ThreadLocal深度理解
      • 多线程循环打印代码
      • 线程等待和唤醒的三种方式
      • ReentrantLock非公平锁的源码分析
    • Java虚拟机

    • 常见面试题

  • 计算机基础

  • 框架|中间件

  • 架构

  • 后端
  • Java
  • Java并发编程
Marvel
2022-07-13
目录

LockSupport工具

# LockSupport工具

# LockSupport介绍

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语,是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。归根结底,LockSupport调用的Unsafe中的native代码。

LockSupport中的park()和unpark()的作用分别是阻塞线程和解除阻塞线程。

LockSupport和每个使用它的线程都有一个许可(permit)关联,permit相当于1,0开关,默认是0。可以把许可看成是一种(0, 1)信号量(Semaphore),但与Semaphore不同的是,许可的累加上限是1。

调用unpark就加1;调用一次park就会消费一个permit,也就是将1变成0,同时park立刻返回。如果再次调用park会阻塞,因为permit变为零会阻塞在这里,直到permit变为1。permit最大值为1,重复调用也不会累加。

LockSupport.park底层:

public static void park() {
	UNSAFE.park(false, 0L);
}
1
2
3

LockSupport.unpark底层:

public static void unpark(Thread thread) {
    if (thread != null)
        UNSAFE.unpark(thread);
}
1
2
3
4

# 三种让线程等待和唤醒的方法?

⭐ 1 使用Object种的wait()方法让线程等待,使用Object中的notify()方法唤醒线程。

public class LockSupportDemo {
    static Object objectLock = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (objectLock) {
                System.out.println(Thread.currentThread().getName() + "\t" + "---come in!");
                objectLock.wait();
                System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒!");
            }
        }, "A").start();
        new Thread(() -> {
            synchronized (objectLock) {
                objectLock.notify();
                System.out.println(Thread.currentThread().getName() + "\t" + "---通知!");
            }
        }, "B").start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意:

  1. wait和notify不能脱离synchronized代码块,会出现java.lang.IllegalMonitorStateException异常

  2. 先notify再wait,notify就起不到任何效果。必须要先等待后唤醒,线程才能被唤醒。

⭐ 2 使用JUC包中的Condition的await()方法让线程等待,使用signal()方法唤醒线程。

public class LockSupportDemo {
    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();

    public static void main(String[] args) {
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "\t" + "---come in!");
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒!");
            } finally {
                lock.unlock();
            }
        }, "A").start();

        new Thread(() -> {
            lock.lock();
            try {
                condition.signal();
                System.out.println(Thread.currentThread().getName() + "\t" + "---通知!");
            } finally {
                lock.unlock();
            }
        }, "B").start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

注意:

  1. condition.await()和condition.signal()要与成对的lock()与unlock()使用,否则会报java.lang.IllegalMonitorStateException异常
  2. 先signal再await,signal不起作用。必须要先等待后唤醒,线程才能被唤醒。

⭐ 3 LockSupport类可以阻塞当前线程以及缓存指定被阻塞的线程。

public class LockSupportDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in!");
            LockSupport.park(); // 阻塞,等待通知放行,它需要许可证
            System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒!");

        }, "A");
        t1.start();

        Thread t2 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---通知!");
            LockSupport.unpark(t1);
        }, "B");
        t2.start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

注意:

  1. 与前面相比,不需要锁块。
  2. 可以先unpark再park。先执行unpark()会导致park()方法形同虚设。
编辑 (opens new window)
#Java#JUC
上次更新: 2023/08/20, 21:21:52
原子类Atomic
抽象队列同步器AQS

← 原子类Atomic 抽象队列同步器AQS→

最近更新
01
位运算
05-21
02
二叉树
05-12
03
Spring三级缓存解决循环依赖
03-25
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Marvel
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式