当前位置: 首页 > news >正文

【多线程开发 4】从源码学习LockSupport

从源码学习LockSupport

2024年6月30日

大家好啊,好久没写博客了,今天打算写一下,讲一下JUC里面LockSupport这个类。

这个是一个工具类,实际上也是为了线程通信开发的。它的源码比较短,也只引用了Unsafe一个类。所以我们可以先看下他的源码:

类注释

他的类注释如下:

Basic thread blocking primitives for creating locks and other synchronization classes.
This class associates, with each thread that uses it, a permit (in the sense of the Semaphore class). A call to park will return immediately if the permit is available, consuming it in the process; otherwise it may block. A call to unpark makes the permit available, if it was not already available. (Unlike with Semaphores though, permits do not accumulate. There is at most one.) Reliable usage requires the use of volatile (or atomic) variables to control when to park or unpark. Orderings of calls to these methods are maintained with respect to volatile variable accesses, but not necessarily non-volatile variable accesses.
Methods park and unpark provide efficient means of blocking and unblocking threads that do not encounter the problems that cause the deprecated methods Thread. suspend and Thread. resume to be unusable for such purposes: Races between one thread invoking park and another thread trying to unpark it will preserve liveness, due to the permit. Additionally, park will return if the caller’s thread was interrupted, and timeout versions are supported. The park method may also return at any other time, for “no reason”, so in general must be invoked within a loop that rechecks conditions upon return. In this sense park serves as an optimization of a “busy wait” that does not waste as much time spinning, but must be paired with an unpark to be effective.
The three forms of park each also support a blocker object parameter. This object is recorded while the thread is blocked to permit monitoring and diagnostic tools to identify the reasons that threads are blocked. (Such tools may access blockers using method getBlocker(Thread).) The use of these forms rather than the original forms without this parameter is strongly encouraged. The normal argument to supply as a blocker within a lock implementation is this.
These methods are designed to be used as tools for creating higher-level synchronization utilities, and are not in themselves useful for most concurrency control applications. The park method is designed for use only in constructions of the form:

while (!canProceed()) {   // ensure request to unpark is visible to other threads ...   LockSupport. park(this);
}

where no actions by the thread publishing a request to unpark, prior to the call to park, entail locking or blocking. Because only one permit is associated with each thread, any intermediary uses of park, including implicitly via class loading, could lead to an unresponsive thread (a “lost unpark”).
Sample Usage. Here is a sketch of a first-in-first-out non-reentrant lock class:

class FIFOMutex {private final AtomicBoolean locked = new AtomicBoolean(false);private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();public void lock() {boolean wasInterrupted = false;// publish current thread for unparkerswaiters.add(Thread.currentThread());// Block while not first in queue or cannot acquire lockwhile (waiters.peek() != Thread.currentThread() || !locked.compareAndSet(false, true)) {LockSupport.park(this);// ignore interrupts while waiting       if (Thread.interrupted()) wasInterrupted = true;}waiters.remove();// ensure correct interrupt status on returnif (wasInterrupted)Thread.currentThread().interrupt();}public void unlock() {locked.set(false);LockSupport.unpark(waiters.peek());}static {     // Reduce the risk of "lost unpark" due to classloadingClass<?> ensureLoaded = LockSupport.class;}
}

第一段文本大意为:

用于创建锁和其他同步类的基本线程阻塞原语。这个类与使用它的每个线程关联一个许可证(在信号量类的意义上)。如果许可证可用,将立即返回停车呼叫,并在此过程中消耗许可证;否则可能会堵塞。如果许可证尚未可用,则调用取消停车使其可用。(但与信号量不同的是,许可证不会累积。最多只有一个。)可靠的使用需要使用易失性(或原子)变量来控制何时停放或取消停放。调用这些的顺序

其实就是对想要枷锁的信息加上一个许可,提前给他许可再消费许可,还是代码走到消费许可后再拿到许可都可以,。

第二段文本大意为:

如果在调用park之前,线程没有发布请求取消park的操作,则会导致锁定或阻塞。因为每个线程只关联一个许可证,任何中间使用park(包括通过类加载隐式地使用)都可能导致线程无响应(“丢失的unpark”)。
样品使用。这是一个先进先出的不可重入锁类的草图:

就是根据第二块代码展示LockSupport具体怎么使用。

代码细节

unpark(Thread thread)

给对应thread发放许可。如果线程被LocjSupport的park()方法阻塞时,使用该方法会被立刻释放运行,如果没有阻塞,则使用该方法发放许可证明时,在下一次调用park()方法,则会直接运行不被阻塞。

park(Object blocker)

会向当前线程请求许可,没有许可就会阻塞,除非发生以下三种情况之一:

  • 其他线程以当前线程为目标调用unpark
  • 其他线程中断当前线程
  • 调用返回

但是park方法不能看出来是哪一个原因导致线程可以重新运行。需要调用的人自己写代码看,例如,线程返回时的中断状态。

parkNanos(Object blocker, long nanos)

和park方法一样,但是有时间限制,到了时间限制也会停止阻塞。

getBlocker(Thread t)

提供阻塞线程t的正在被阻塞的park方法是谁调用的,但是线程不安全,拿到这个对象操作的时候可能也已经被unpark了也说不定。

park()

直接禁用当前线程。

private LockSupport() {} // Cannot be instantiated.

LockSupport不能被初始化,只能使用LockSupport进行开发

setCurrentBlocker(Object blocker)

该方法可以做到在blocker使用park()方法之前会调用该方法,可以做到一些分析的作用。

总结

这个方法比较简单,但是比较方便进行线程间通信。

http://www.lryc.cn/news/389237.html

相关文章:

  • gameui C++的代码
  • 1.什么是js?特点是什么?组成部分?
  • 爬虫是什么?
  • 深入理解Presto分页查询:方法与最佳实践
  • 如何使用Go语言中的并发函数实现网络爬虫的分布式部署?
  • STM32第九课:DHT11温湿度传感器
  • JVM线上监控环境搭建Grafana+Prometheus+Micrometer
  • MyBatis(17)MyBatis 如何处理枚举类型
  • 云数据中心运维新纪元:让Linux服务器如虎添翼
  • C# 多线程造成CPU占用率高
  • 谈谈在不同公司中的SAP职位
  • 服务器连接不上
  • 论文辅导 | 基于贝叶斯优化-卷积神经网络-双向长短期记忆神经网络的锂电池健康状态评估
  • 安卓实现微信聊天气泡
  • 软件测试(功能、接口、性能、自动化)详解 | 测试人生路
  • 【面试题】网络IO模型
  • 数据结构-----【链表:基础】
  • 如何在pycharm里面运行pytest用例
  • Charles抓包工具踩坑记录
  • 【RabbitMQ实战】邮件发送(直连交换机、手动ack)
  • python 笔试面试八股(自用版~)
  • 《SpringBoot+Vue》Chapter04 SpringBoot整合Web开发
  • 腾讯地图异步调用
  • 通过docker overlay2 目录名查找占用磁盘空间最大的容器名和容器ID
  • 每周算法:有向图强连通分量
  • Python习题 053:在逻辑值检测时会被认为是真值的是?
  • 基于RackNerd + CentOS 7 64 Bit + aaPanel 的那些事
  • 大数据期末复习——hadoop、hive等基础知识
  • 什么是客户体验自动化?
  • 高效除氟:探索CH-87up树脂在氟化工废水处理中的应用