博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java大厂高频面试题第三季
阅读量:2455 次
发布时间:2019-05-10

本文共 2587 字,大约阅读时间需要 8 分钟。

文章目录

学习方法:
1、是什么
2、能干嘛
3、去哪下
4、怎么玩

JUC

可重入锁

可重入锁又名递归锁。

是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提,锁对象得是同一个对象),不会因为之前已经获取过还没释放而阻塞。

Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁。

可: 可以。重: 再次。入: 进入。锁: 同步锁。

LockSupport 加强版等待唤醒机制

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。

LockSupport中的park()unpark()的作用分别是阻塞线程和解除阻塞线程。
是一个线程等待唤醒机制的加强版。

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

  • 使用Object中的wait()方法让线程等待, 使用Object中的notify()方法唤醒线程。
  • 使用JUC包中Conditionawait()方法让线程等待,使用signal()方法唤醒线程。
  • LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程。

传统的 synchronized 和 Lock 实现等待唤醒通知的约束:

  • 线程先要获得并持有锁,必须在锁块(synchronized或lock)中。
  • 必须要先等待后唤醒,线程才能够被唤醒。

LockSupport 案例:

import java.util.concurrent.locks.LockSupport;/** *   LockSupport不用持有锁块,不用加锁,程序性能好 *   先后顺序,不容易导致卡死 */public class LockSupportDemo {
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t wait park"); // 阻塞当前线程 LockSupport.park(); System.out.println(Thread.currentThread().getName() + "\t park end"); }, "Thread-1"); t1.start(); TimeUnit.SECONDS.sleep(2); LockSupport.unpark(t1); }}

先唤醒后等待,LockSupport也支持:

public class LockSupportDemo {
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) {
e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "\t wait park " + System.currentTimeMillis()); // 阻塞当前线程 LockSupport.park(); System.out.println(Thread.currentThread().getName() + "\t park end" + System.currentTimeMillis()); }, "Thread-1"); t1.start(); LockSupport.unpark(t1); }}

在这里插入图片描述

LockSupport原理总结:
LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。
归根结底,LockSupport调用的Unsafe中的native代码。

LockSupport和每个使用它的线程都有一个许可(permit)关联。permit相当于1,0的开关,默认是0,调用一次unpark就加1变成1,调用一次park会消费permit,也就是将1变成o,同时park立即返回。

如再次调用park会变成阻塞(因为permit为零了会阻塞在这里,一直到permit变为1),这时调用unpark会把permit置为1。

每个线程都有一个相关的permitpermit最多只有一个,重复调用unpark也不会积累凭证。

形象的理解

线程阻塞需要消耗凭证(permit),这个凭证最多只有1个。
当调用park方法时:

  • 如果有凭证,则会直接消耗掉这个凭证然后正常退出
  • 如果无凭证,就必须阻塞等待凭证可用

unpark则相反,它会增加一个凭证,但凭证最多只能有1个,累加无效。

面试题:

为什么可以先唤醒线程后阻塞线程?
因为unpark获得了一个凭证,之后再调用park方法,就可以名正言顺的凭证消费,故不会阻塞。

为什么唤醒两次后阻塞两次,但最终结果还会阻塞线程?

因为凭证的数量最多为1,连续调用两次unpark和调用一次unpark效果一样,只会增加一个凭证;
而调用两次park却需要消费两个凭证,证不够,不能放行。

AQS

AbstractQueuedSynchronizer 简称为AQS。

抽象的队列同步器。

Redis 五大基本类型

在这里插入图片描述

String

Hash

List

Set

Zset

转载地址:http://mfchb.baihongyu.com/

你可能感兴趣的文章
公众号精选评论点赞_十大和编辑精选:三月评论
查看>>
python中flask_为什么以及如何在Python Flask中处理异常
查看>>
适合初学者的开源c需要项目_您的开源项目需要总裁吗?
查看>>
Python脚本可自动替换Scribus中的文本
查看>>
代码交互式图文_围绕交互式代码构建教室
查看>>
公众号精选评论点赞_十大和编辑精选:七月评论
查看>>
软齿面减速机抛开图_为了共同的目标而抛开自我
查看>>
维度诅咒_CEO自我的礼物和诅咒
查看>>
如何使用Jenkins运行JMeter
查看>>
angular 初探_初探Google的Science Journal应用
查看>>
关于开源软件研究的英文论文_关于开源公司软件的7个神话
查看>>
非传统营销 text_在传统营销失败的地方,社区推动的营销成功
查看>>
irc ubuntu_IRC入门
查看>>
Phire CMS:功能丰富的轻量级内容管理系统
查看>>
庆祝一下_加入我们,庆祝开放组织的一年
查看>>
dropbox为什么被屏蔽_Python社区和Dropbox为增加多样性而采取的步骤
查看>>
路由器搭建个人网站_PittMesh路由器归个人所有
查看>>
raspberry pi_Picademy:Raspberry Pi基金会的老师的免费专业发展
查看>>
retropie游戏版权_RetroPie的新网站和发行版,针对Linux的三款新游戏以及更多游戏新闻...
查看>>
开源项目贡献者_在现代开源中发展贡献者基础
查看>>