LockSupport源码解析
JUC包中进行线程阻塞和线程唤醒的时候使用了一个工具类,这个类就是LockSupport,在AQS中对线程的阻塞和唤醒就是依靠此类完成的,那么LockSupport是如何实现的里?确实当时我们只是大概知道了基本的过程,并没有进行深入。因为在AQS中我们知道有一个线程链表,链表的每个节点就是Node。
为了让我们的思维更加有理有据,所以我觉得又到了整理一下思维的时候。我们知道多线程代码在跑的时候遇到独占锁的时候才会加入我们上边说的Node,也才会进行单核CPU运行。而AQS链表也只是取第一个节点进行运行。这么看来这个队列本来就具有一种特点就是可以阻塞了。那么为啥还要用一个工具类?比如说我这个链表第一个运行完毕了,然后要唤醒其他线程。我应该用for循环去唤醒吗?看来好像有点问题,我们无法保证没有人抢跑。有鉴于此还是看一下源码,来看看为啥用的这么一个工具类。以及这个工具类干了些什么。
首先引入眼帘的是LockSupport的静态代码块,发现使用到了Unsafe的内存操作。如果用内存操作那么肯定要用到偏移量什么了,这在代码均有体现。然后通过Unsafe类来Thread类中的属性偏移量,那么记录这些偏移量的意义是什么?为什么要这么做?怀着疑问继续前进。但是发现在LockSupport类中好像就剩下方法了。那么还是按照之前的操作,从加锁开始吧。。
// Hotspot implementation via intrinsics API
private static final sun.misc.Unsafe UNSAFE;
private static final long parkBlockerOffset;
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> tk = Thread.class;
parkBlockerOffset = UNSAFE.objectFieldOffset
(tk.getDeclaredField("parkBlocker"));
SEED = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSeed"));
PROBE = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
} catch (Exception ex) { throw new Error(ex); }
}
我们在加锁时候一般调用的是lock,而lock最后也是采用的LockSupport提供的park方法。park就是让一个线程阻塞的方法。因为LockSupport是一个工具方法,所以我们在AQS中看看是如何使用这个工具的。
我们看到AQS在调用的时候将this传入了,this就是AQS本身,AQS包含了他多的类。如果这样的话,LockSupport就成为皇家专属产品,我们这种屌丝看来也用不到了。。zz,是这样么?咋还是不要轻易下结论。
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
在park方法中,首先获取当前线程,然后和AQS做为参数调用了setBlocker方法。这里好像用了两次哦,,,感觉要复杂了。。。
private static void setBlocker(Thread t, Object arg) {
// Even though volatile, hotspot doesn't need a write barrier here.
UNSAFE.putObject(t, parkBlockerOffset, arg);
}
在setBlocker方法中也是直接调的Unsafe的方法,看来是完全不给咋理解的机会啊,那么没办法,咋只能猜啊。因为这个offset是Thread类中的一个变量。而这个变量是Volatile修饰的而Unsafe一般都是操作这中修饰的属性的,况且这个offset就是也是从thread类中获取的,那么这里应该就是往当前线程里设置AQS。那么设置了AQS之后,有很么用呐?通过搜索之后发现这里不一定要设置成AQS,就是LockSupport并不是皇家专用,这里的AQS其实就是线程阻塞的调用者。而Unsafe.park其实也就是让线程停下来。那么在线程停下来之后为啥要设置调用者为null?我的感觉是用不到了这个调用者了那么就不要了。。多么简单的解释。其实我不太懂,但感觉是这样的,只能说park方法里可能要用这个,然后用完之后就不用了。
代码看到这里的时候就觉得这个类已经没啥了。就是让线程睡眠而已。
那么我们继续看一下unpark这个方法。发现也是直接操作的内存进行唤醒线程。
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
总结一下LockSupport
第一为是阻塞线程和唤醒线程,同时LockSupport提供了多种阻塞的方法。
第二在阻塞线程的时候将调用者设置到被阻塞线程的Blocker属性中,用于某种日志操纵。
- Python基础10 反过头来看看
- CCCF 微软沈向洋:理解自然语言:表述、对话和意境
- Linux进程基础
- Android Studio导入项目非常慢的解决办法
- Android开发中遇到的requestFeature() must be called before adding content异常
- Linux信号基础
- 剑指OFFER之合并有序链表(九度OJ1519)
- Android Studio快捷键每日一练(6)
- Linux文本流
- Linux并发与同步
- Android Studio快捷键每日一练(5)
- 2017年移动行业五大发展趋势及2018年前景展望(下)
- 剑指OFFER之反转链表(九度OJ1518)
- Android Studio快捷键每日一练(4)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ThinkPHP3.2.3框架实现的空模块、空控制器、空操作,跳转到错误404页面图文详解
- PHP示例演示发送邮件给某个邮箱
- PHP设计模式之观察者模式定义与用法分析
- PHP实现数组向任意位置插入,删除,替换数据操作示例
- 实例讲解Python 迭代器与生成器
- opencv 图像轮廓的实现示例
- 基于python实现可视化生成二维码工具
- Python word实现读取及导出代码解析
- Python项目跨域问题解决方案
- keras的load_model实现加载含有参数的自定义模型
- opencv 图像加法与图像融合的实现代码
- PHP图像处理技术实例总结【绘图、水印、验证码、图像压缩】
- python如何实现读取并显示图片(不需要图形界面)
- PHP文件操作实例总结【文件上传、下载、分页】
- Django中Aggregation聚合的基本使用方法