2/15

1.内置锁和lock区别。底层实现原理
内置锁说的就是Synchronized(moinitor锁对象)
外置锁lock(CAS+AQS)
区别:
Synchronized是java关键字,Lock是一个类。
Synchronized非公平锁,Lock默认公平锁,但可实现非公平锁。
Synchronized无法判断锁的状态、不可中断。Lock可以判断且可以中断。
锁的释放不一样,Synchronized执行完同步代码,释放锁。Lock必须在finally中释放锁
锁的获取不一样,Synchronized得不到锁就一直等着,Lock四种方式获得锁,不用一直等待。
Lock原理(CAS+AQS)
CAS:锁状态的变量(0表示没有线程获取锁,1表示已有线程占有锁),该变量必须声明为voaltile类型;0到1的转换由CAS负责
AQS:AQS其实就是一个可以给我们实现锁的框架
内部实现:先进先出的队列、state状态
如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,CAS将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞 等待以及被唤醒时锁分配的机制,这个机制AQS即将暂时获取不到锁的线程加入到阻塞队列尾部中。线程唤醒也只会唤醒队列最前部的。
用大白话来说,AQS就是基于FIFO队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒(唤醒了就是就绪状态不是运行态哦)。
**注意:AQS是自旋锁:**在等待唤醒的时候,经常会使用自旋(while(!cas()))的方式,不停地尝试获取锁,直到被其他线程获取成功
2.公平锁和非公平锁,哪个效率高?
非公平锁效率会更高。
公平锁按照请求的顺序获得锁,先到的线程优先获得锁。不公平锁意味着后请求锁的线程可能在其前面排列的阻塞线程恢复前拿到锁,这样就有可能提高并发的性能。
3.哪些类底层用到了CAS(CAS是原子的!!!!!!)
CAS用到了操作底层的Unsafe类中的CompareAndSwap方法
Lock类
java.util.concurrent.atomic 包下的类原子类大多是使用CAS操作来实现的
(eg. AtomicInteger.java,AtomicBoolean,AtomicLong)
4.Java中的int和Integer有什么异同?你觉得int a = 128和Integer a = new Integer(128)一样吗?
Ingeter是int的包装类(是个类哦),int的初值为0,Integer的初值为null
int是8种基础数据类型的一种,它的字节长度为4,用于表示现实中的正负整型数字。由于它属于基础数据类型,它的创建不会在堆内存中开辟空间,一般是保存在桟内存中的 ,它可以用算术运算符进行加,减,乘,除等操作。在参数传递的时候,直接传递它的值。
Integer是int的包装类,它本质是一个类,它的创建会在堆内存中开辟一块新的空间。它的含义也是表示一个整型的数字,但是,算术运算符不能操作它。在参数传递的时候,传递的是它所代表的对象的一个引用。
5.三次握手
SYN用来发起连接,所以前两个有SYN代表通知对方要连接。
ACK=1,只有为1才是确认表示。所以第一个没有ACK
ack代表期望 要的数据是什么
seq数据包***
客户端传i,i+1,i+2… 服务器传j,j+1,j+2…
2/15
为什么是三次握手,而不是两次或者四次?
防治之前失效的连接请求到达服务器,让服务器错误打开连接。服务器的资源会被白白“浪费”。所以两次肯定不行
四次的话客户端等待时间过长。
四次挥手
FIN这个和连接的SYN很像,用于释放链接。
服务器首先传送的是之前还没有传完的报文,只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手 seq=v就是以前的数据,所以没有ack=v+1
2/15
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
我们必须假想网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再等待2MSL。
6.jvm 的局部变量表是做什么的?
首先你搞清楚局部变量表在哪里:
在java虚拟机栈中
void fun () {
int a = 0;
int b = 1;
int c = 2;
}
这就是一个长度为4的局部变量表
用来存储方法参数和方法内部定义的局部变量 。局部变量表的容量是以变量槽 为最小单位的。其中long和double会占用两个局部变量空间,其余的只占1个空间。局部变量表所需要的内存空间在编译期已经完成分配。
7.双亲委派有了解吗?
类加载器加载类时先委派给父类加载,只有父类无法加载时,自己才尝试加载。
8.为什么要双亲委派?
保证java类库中的类不受用户类影响,防止用户自定义一个类库中的同名类,引起问题。
9.垃圾回收怎么判断哪些对象应该回收?
可达性分析,从 GCRoot 开始遍历,不能遍历到的对象就可以认为已经死了,可以回收。
**10.什么可以作为GCRoot?**就是没有堆
虚拟机栈(栈帧中的本地变量表)中引用的对象。
本地方法栈中(native方法)引用的对象。
方法区中的静态变量 和常量引用的对象。类嘛
11.线程池的中的线程数量能不能无限增加,为什么?
不能,线程需要一定开销,太多线程会耗尽计算机资源,(而且过多线程也无法发挥多线程的优势,毕竟cpu核就那么多)
12.java 里任务提交给线程池后,那些任务是存储在哪的?
是把任务用 Runable(其实也可以是Callable) 表示,放在一个阻塞队列里。
13.阻塞队列BlockingQueue怎么实现?
发生阻塞起码得满足下面至少一个条件: (前提:队列是有界的)
1.从队列里取元素时,如果队列为空,则代码一直等在这里(即阻塞),直到队列里有东西了,拿到元素了,后面的代码才能继续
2.向队列里放元素时,如果队列满了(即放不下更多元素),则代码也会卡住,直到队列里的东西被取走了(即:有空位可以放新元素了),后面的代码才能继续
 ArrayBlockingQueue:基于数组 实现的一个阻塞队列,在创建ArrayBlockingQueue对象时必须制定容量大小 。并且可以指定公平性与非公平性,默认情况下为非公平的,即不保证等待时间最长的队列最优先能够访问队列。
LinkedBlockingQueue:基于链表 实现的一个阻塞队列,在创建LinkedBlockingQueue对象时如果不指定容量大小,则默认大小为Integer.MAX_VALUE。
PriorityBlockingQueue:以上2种队列都是先进先出队列 ,而PriorityBlockingQueue却不是,它会按照元素的优先级对元素进行排序,按照优先级顺序出队,每次出队的元素都是优先级最高的元素 。注意,此阻塞队列为*阻塞队列,即容量没有上限 (通过源码就可以知道,它没有容器满的信号标志),前面2种都是有界队列。
DelayQueue:基于PriorityQueue,一种延时阻塞队列,DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue也是一个*队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞 ,而只有获取数据的操作(消费者)才会被阻塞。
方法\处理方式 抛出异常 返回true/false 一直阻塞 超时退出
插入方法 add(e) offer(e) put(e) offer(e,time,unit)
移除方法 remove() poll() take() poll(time,unit)
检查方法 element() peek()
4类方法中,在队列已满(或为空)的情况下,有些会抛出异常,有些则返回true/false,有些则一直阻塞,还有些则可以设置超时时间,时间到了后,自动退出阻塞状态,实际项目中可根据需要选取适合的方法。
14.讲一下 volatile 。内存可见性、指令重排、32位jvm对64数据的原子操作什么的
编译多了lock内存屏障。
内存屏障作用:
确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;它会 强制将对缓存的修改操作立即写入主存;如果是写操作,它会导致其他CPU中对应的缓存行无效。
32位的JVM会将64位数据的读写操作分为2次32位的读写操作来进行 ,这就导致了long、double类型的变量在32位虚拟机中是非原子操作,数据有可能会被破坏,也就意味着多个线程在并发访问的时候是线程非安全的。
所以对于64位的long和double,如果没有被volatile修饰,那么对其操作可以不是原子的。 在操作的时候,可以分成两步,每次对32位操作;
如果使用volatile修饰long和double,那么其读写都是原子操作;
在JVM时,可以*选择是否把读写long和double作为原子操作;
**15.volatile 可以保证并发计数正确性?**不能
16.如果需要保证并发计数正确怎么办,只能加锁吗? java 有原子变量,于是说 AtomicInteger。
17.tcp了解吗,说一下滑动窗口
独立字节数据当做流来处理。
“窗口”对应的是一段可以被发送者发送的字节序列,其连续的范围 称之为“窗口”;“滑动”则是指这段“允许发送的范围”是可以随着发送的过程而变化的,方式就是按顺序“滑动”
18.tcp的拥塞控制(滑动窗口+一系列算法)怎么实现
防止过多的数据 注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。
拥塞444444444控制由4个核心算法组成:“慢启动”、“拥塞避免”、“快速重传 ”、“快速恢复”
慢启动:指数增长。
cwnd窗口>ssthresh阈值:线性增长。
拥塞避免:发生了拥塞,ssthresh减半,cwnd从1开始慢启动。
2/15
快重传和快恢复则是为了减少因为拥塞导致的数据包丢失带来的重传时间
-1.如果一个包丢失,则对后续的包继续发送针对该包的重传请求;
-2. 一旦发送方接收到三个一样的确认,就知道该包之后出现了错误,立刻重传该包;
-3. 此时发送方开始执行“快恢复”算法:
*1. ssthresh减半;
*2. cwnd设为慢开始门限减半后的数值;
*3. 执行拥塞避免算法(高起点,线性增长);
2/1519.操作系统的内存是怎么分配的
首先了解一下内存层次
2/15
连续地址空间分配 (静态、动最先、动最优、动最差):静态会造成内部 …动态的外部碎片
非连续地址空间分配:分段或者分页
20.哪个集合可以实现stack,queue,deque
LinkedList 类实现了接口 Queue 和 Deque和Stack
别的还有么?我不确定