在 1:1 模型中,启动一个用户线程,就会同时创建一个内核线程(注意,这里是启动线程,不是创建线程)。
每个用户线程在其整个生命周期内,都会被映射或绑定到一个内核线程上。当用户线程声明周期结束,两个线程则一起退出。无论是用户进程的线程,或者是系统进程的线程,他们的创建、撤销、切换都是依靠内核实现的。所以该模式下,CPU在线程的切换开销比较大。

Java 语言采用的便是这种线程模型。
用户线程:语言层面创建的线程,比如 java语言中多线程技术,通过语言提供的线程库来创建、销毁线程。
内核线程:内核线程又称为守护线程 Daemon线程,用户线程的运行必须依赖内核线程,通过内核线程调度器来分配到相应的处理器上。

• 基本类型:AtomicInteger, AtomicLong, AtomicBoolean.
• 数组类型:AtomicIntegerArray, AtomicLongArray.
• 引用类型:AtomicReference, AtomicStampedRerence.
• 对象的属性修改类型:AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater.

UnSafe类+CAS思想(自旋)
AtomicInteger
CAS->UnSafe->CAS底层思想->ABA->原子引用更新->如何规避ABA问题
是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式尝试获取锁,这样做的好处是减少线程上下文的切换的消耗,缺点是循环会消耗CPU

public class SpinLockDemo {

// 原子引用线程
AtomicReference<Thread> atomicReference= new AtomicReference<>();public void MyLock(){Thread thread=Thread.currentThread();System.out.println(Thread.currentThread().getName()+"\t come in  ");while (!atomicReference.compareAndSet(null,thread)){}
}public  void  MyUnLock(){Thread thread =Thread.currentThread();System.out.println(Thread.currentThread().getName()+"\t invoked MyUnLock  ");atomicReference.compareAndSet(thread,null);
}public static void main(String[] args) {SpinLockDemo spinLockDemo=new SpinLockDemo();new Thread(()->{spinLockDemo.MyLock();try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}spinLockDemo.MyUnLock();},"AAA").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{spinLockDemo.MyLock();try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}spinLockDemo.MyUnLock();},"BBB").start();}

}

1、自旋锁

自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。如下

public class SpinLock {

private AtomicReference sign =new AtomicReference<>();

public void lock(){

Thread current = Thread.currentThread();

while(!sign .compareAndSet(null, current)){

}

}

public void unlock (){

Thread current = Thread.currentThread();

sign .compareAndSet(current, null);

}

}

使用了CAS原子操作,lock函数将owner设置为当前线程,并且预测原来的值为空。unlock函数将owner设置为null,并且预测值为当前线程。

当有第二个线程调用lock操作时由于owner值不为空,导致循环一直被执行,直至第一个线程调用unlock函数将owner设置为null,第二个线程才能进入临界区。

由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。但当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。如果线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。

多线程编程中一般线程的个数都大于 CPU 核心的个数,而一个 CPU 核心在任意时刻只能被一个线程使用,为了让这些线程都能得到有效执行,CPU 采取的策略是为每个线程分配时间片并轮转的形式。当一个线程的时间片用完的时候就会重新处于就绪状态让给其他线程使用,这个过程就属于一次上下文切换。
最大的区别在于等待自旋锁/互斥锁的线程的状态不一样。等待自旋锁的线程不会挂起并让出cpu,而是一直轮询直到获取自旋锁,所以如果一直获取不到自旋锁则会导致"线程饥饿"。等待互斥锁的线程则会进入睡眠状态让出cpu,等待唤醒。自旋意味着不断重试直到成功。
共同点在于某一个时刻都只有被一个线程持有。

像synchronized这种独占锁属于悲观锁,它是在假设一定会发生冲突的,那么加锁恰好有用,除此之外,还有乐观锁,乐观锁的含义就是假设没有发生冲突,那么我正好可以进行某项操作,如果要是发生冲突呢,那我就重试直到成功,乐观锁最常见的就是CAS。

CAS操作
我们学过两个关键字synchronized与volatile,两者都可以解决共享变量内存可见性的问题,但是,volatile不能解决读-改-写等原子性的问题,synchronized能够解决原子性问题,但是其性能开销大。

CAS操作是Compare And Swap,是JDK提供的非阻塞原子性操作,通过硬件保证了比较-更新操作的原子性。JDK里面的Unsafe类提供了一系列compareAndSwap*方法,比如compareAndSwapInt和compareAndSwapLong。下面我们以compareAndSwapLong为例子进行简单介绍。

boolean compareAndSwapLong(Object obj,long valueOffset,long expect,long update)方法:四个参数,含义分别是:对象内存位置,对象中变量的偏移量,变量的预期值,新的值。其操作的含义是,若对象obj中内存偏移量为valueOffset的变量值为expect,则用新的值update替换旧的值,也就是替换expect。这是处理器提供的一个原子性命令。

CAS操作虽然很高效地解决了原子操作,但是仍然存在三大问题:ABA问题、循环开销时间大、只能保证一个共享变量的原子操作

ABA问题 CAS在操作值得时候,会检查值有没有发生变化,如果没有发生变化就更新。若是一个值原来是A,变成了B,后来又变回了A(举例:线程1获取变量值为A后,在执行CAS之前,线程2使用CAS修改变量的值为B,然后又修改变量值为A),那么使用CAS操作时检查其值得结果是没有变化,但其实是变化了,虽然线程1执行CAS操作时变量的值为A,但是这个A已经不是线程1获取变量值时的A了,这就是ABA问题。
看起来好像最后还是正确的修改了变量值,但其实是丢失了变量值得修改记录。此问题的解决方案就是使用版本号,在变量前面追加上版本号,每次变量更新的时候把版本号+1,这样A-B-A就会变为1A-2B-3A。从Java1.5开始,JDK的Atomic包里就提供了一个类AtomicStampedReference来解决ABA问题,其中compareAndSet方法的作用就是,先检查当前引用是否等于预期引用,并检查当前标志是否等于预期标志,如果全部相等,就进行更新。

public boolean compareAndSet(V expectedReference,//预期引用
V newReference,//更新后引用
int expectedStamp,//当前标志
int newStamp)//更新后标志
循环时间长,开销大 自旋CAS如果长时间不成功,会给CPU带来非常大的开销。
只能保证一个共享变量的原子操作 当对一个共享变量执行操作的时候,我们可以使用CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁。从Java1.5开始,JDK的Atomic包里就提供了一个类AtomicReference类来保证引用对象直接的原子性,就可以多个变量放在一个对象里来进行CAS操作。
compareAndSet 比较去设置
例如:
CAS处理数据时:加入要操作的变量是i
则:
int tmp = i;
int j = i+1;
compareAndSet(i, tmp, j)
就是会有个临时变量:在执行CAS时,会判断临时变量k是否还和i的值一样,如果不一样则重新执上述步骤,如果一样则更改


应用层协议有什么 HTTP、DNS、FTP、SMTP
应用层协议如下:

(1)域名系统(Domain Name System,DNS):用于实现网络设备名字到IP地址映射的网络服务。

(2)文件传输协议(File Transfer Protocol,FTP):用于实现交互式文件传输功能。

(3)简单邮件传送协议(Simple Mail Transfer Protocol, SMTP):用于实现电子邮箱传送功能。

(4)超文本传输协议(HyperText Transfer Protocol,HTTP):用于实现WWW服务。

(5)简单网络管理协议(simple Network Management Protocol,SNMP):用于管理与监视网络设备。

(6)远程登录协议(Telnet):用于实现远程登录功能。

为什么说B+树比B树更适合数据库索引?
1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

3、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

java面经无规则刷题-理解记忆相关推荐

  1. java二叉树转换为链表_leetcode刷题笔记-114. 二叉树展开为链表(java实现)

    leetcode刷题笔记-114. 二叉树展开为链表(java实现) 题目描述 给你二叉树的根结点 root ,请你将它展开为一个单链表: 展开后的单链表应该同样使用 TreeNode ,其中 rig ...

  2. java计算机毕业设计软考刷题系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计软考刷题系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计软考刷题系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开 ...

  3. 【JAVA】acwing语法基础课刷题(138 / 138)完结

    目录 一.输入输出 1.低效率 - 输入输出 2.高效率 - 输入输出 1.输入规模较大时使用 2.输出规模较大时使用 二.判断语句和循环语句 !简单斐波那契 !试除法求约数 !试除法判断约数726. ...

  4. 【java】牛客网刷题

    1. 给出以下代码 public class TestObj{public static void main(String[] args){Object o=new Object(){public b ...

  5. 程序员,别再无脑刷题了,这样学 Python,编程能力暴增!

    听说 Python 很难学?难在哪里?听说学完不知道做什么?为什么?Python 该怎么学?好不好学?学完做什么?许多人都会遇到了下面这些问题--1. 没经验根本不知道从何学起,而且应用方向太多了也不 ...

  6. 大一就开始这样刷题后,我成了同学们眼中的 offer 收割机

    CSDN 的小伙伴们,大家好,我是五一也没有闲着的二哥. 之前不是给大家分享了一份 Java 版的 LeetCode 刷题笔记嘛,很多小伙伴留言说刚好需要,对我这种大公无私的分享精神表示敬佩(嘘. 但 ...

  7. 如何看待为了进 Google、微软等外企大量刷题?

    来源:https://www.zhihu.com/question/35133069 编辑:深度学习与计算机视觉 声明:仅做学术分享,侵删 作者:程墨Morgan https://www.zhihu. ...

  8. 关于考试刷题的一些感想

    考试,就是在规定的时间内,考察一个人的能力.但是,规定的时间如何能考察一个人的能力?考察的就全面?它不全面!既然不全面,既然有不足,就有可突破的点. 考试,不在于以一己之力,攻克所有困难的问题.说白了 ...

  9. Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤...

    TCP和UDP是两个传输层协议,广泛应用于网络中不同主机之间传输数据.对任何程序员来说,熟悉TCP和UDP的工作方式都是至关重要的.这就是为什么TCP和UDP是一个流行的Java编程面试问题. Jav ...

最新文章

  1. numpy 点乘_Numpy入门指南
  2. TCP/IPICMP报文的分类
  3. oracle xml中cdata,XML CDATA的作用
  4. Css颜色和文本字体
  5. python实现批量图片/文件重命名
  6. 信息学奥赛C++语言: 单词的长度
  7. 美团猫眼电影Android模块化实战总结
  8. MSSQL数据库初级到高级的学习资料整理
  9. 扬州工业机器人外壳设计排名_世界十大工业机器人制造商公布,排名第一的竟是……...
  10. RoboCup智能机器人足球教程(四)
  11. 论文阅读:CVPR2021 | Involution: Inverting the Inherence of Convolution for Visual Recognition
  12. python调用dll文件
  13. QPushButton禁用状态文字变形变粗
  14. 快速分区MBR和GUID的区别
  15. 利用Matlab将图片转换成素描(简笔画)风格
  16. 今天是七夕节了,你想好怎么表白了吗?
  17. Json Web Token(JWT)
  18. 【算法和数据结构学习笔记】整合版
  19. 完全开源Android项目:PDF电子书架软件——不动的大图书馆
  20. 模拟退火算法求解TSP问题(python)

热门文章

  1. [转载]大道至简!!!从SAP HANA作为SAP加速器的方式,看ERP on HANA的春天
  2. 【厂妹进谷歌】从富士康流水线小妹到 Google 工程师,She made it !!!
  3. JavaScript 显示和隐藏图片
  4. 第十八届全国大学智能汽车竞赛报名信息统计:华北赛区报名队伍
  5. 计算机主机可以有几块硬盘,最好将计算机硬盘分为几个区域. 硬盘分区原理
  6. 信息系统工程监理师一味的应和建设单位要求解决方法
  7. 频繁默认网关不可用_win10系统默认网关不可用频繁掉线的具体方法
  8. 【大咖有约】华为叶涛:数据库事务处理的原理与实例剖析
  9. 微信浏览器禁止app下载链接怎么办怎么解决
  10. win10 体验 日志