欢迎光临散文网 会员登陆 & 注册

锁屏面试题百日百刷-java大厂八股文(day2)

2021-07-26 22:21 作者:zjlala96  | 我要投稿


为了有针对性的准备面试,锁屏面试题百日百刷开始每日从各处收集的面经中选择几道经典面试题分享并给出答案供参考,答案中会做与题目相关的扩展,并且可能会抛出一定问题供思考。这些题目我会标注具体的公司、招聘类型(校招、社招、实习)以及面试阶段。这些面试题会收录到锁屏面试题app和小程序中并整理归类好。其他面试题也同样在持续更新中,多谢使用和支持。下面是今日面试题:


====HashMap为什么线程不安全?ConcurrentHashMap的原理?[字节跳动][校招][面]

HashMap不安全的地方:

HashMap在new的时候并不会初始化,而是在第一次 put 的时候,会进行哈希数组的初始化,如下图:

 


(resize方法这里不说,建议去了解下,因为这个涉及到面试的另一个常问点,HashMap的原理。)

要是两个线程做put操作,且恰好判断tab(如上图)的长度为空,则会存在两次对 HashMap 进行初始化,这样就会有两个哈希数组。所以说线程不安全的。

另外在HashMap中put、remove等方法因为没有添加锁,也存在线程安全问题。

ConcurrentHashMap的原理:

 

在1.8中,ConcurrentHashMap使用数组+单向链表+红黑树的数据结构保存数据,采用Node + CAS + Synchronized实现分段锁的形式来保证并发操作安全进行。

 

这里扩展讲一下ConcurrentHashMap实现初始化hash表的过程,其他的put、remove等操作在后面的面试题中遇到再讲,感兴趣的可以看一看ConcurrentHashMap源码。

 

如与HashMap中一样,ConcurrentHashMap也是在put中做初始化hash表的操作,它首先设置了一个sizeCtl变量,这个变量的默认值是0,当我们做初始化hash表操作时,通过CAS操作(图中代码U.compareAndSwapInt(this, SIZECTL, sc, -1))将其置为-1,然后我们再进行初始化(初始化完成后,我们需要在 finally 代码块中把 sizeCtl 设置回 0 的值),设置这个sizeCtl为-1的原因是所有的线程在判断hash表为空的时候,要想初始化hash表得判断这个sizeCtl

不小于0,如果小于0说明有其他线程在初始化hash表,就会使用Thread.yield()让当前线程放弃时间片就算当前线程又抢到了时间片,它还是会在这个while中(我们称为自旋),知道hash表初始化完成,也就不用再进行初始化了,while条件也不再成立,但是得注意变量table(hash表)和sizeCtl必须为volatile,保证其可见性。

1.7中,ConcurrentHashMap采用Segment + HashEntry的结构,Segment是一种可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组。Segment的结构和HashMap类似,是一种数组和链表结构。一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得与它对应的Segment锁,如下图所示。


====讲下https?[shopee][校招][面]

http(Hyper Text Transfer Protocol)协议是对客户端和服务器端之间数据之间实现可靠性的传输文字、图片、音频、视频等超文本数据的规范,格式简称为“超文本传输协议”,http协议属于应用层。

https实现的原理:

一、首先HTTP请求服务端生成证书,客户端对证书的有效期、合法性、域名是否与请求的域名一致、证书的公钥(RSA加密)等进行校验;

 

二、客户端如果校验通过后,就根据证书的公钥的有效, 生成随机数,随机数使用公钥进行加密(RSA加密);

 

三、消息体产生的后,对它的摘要进行MD5(或者SHA1)算法加密,此时就得到了RSA签名;

 

四、发送给服务端,此时只有服务端(RSA私钥)能解密。

 

五、解密得到的随机数,再用AES加密,作为密钥(此时的密钥只有客户端和服务端知道)。


更多面试题或学习资源可查看我主页或评论获取


锁屏面试题百日百刷-java大厂八股文(day2)的评论 (共 条)

分享到微博请遵守国家法律