前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >java内存模型之volatile核心原理与应用

java内存模型之volatile核心原理与应用

原创
作者头像
Java程序猿
修改于 2021-03-17 09:55:14
修改于 2021-03-17 09:55:14
4380
举报
文章被收录于专栏:Java核心技术Java核心技术

前言

在阅读本文前,请思考以下的面试题?

  • volatile是什么?
  • volatile的特性
  • volatile是如何保证可见性的?
  • volatile是如何保证有序性的?
  • volatile可以保证原子性吗?
  • 使用volatile变量的条件是什么?
  • volatile和synchronized的区别
  • volatile和atomic原子类的区别是什么?

这一章主要是讲解volatile的原理,在开始本文前,我们来看一张volatile的思维导图,先有个直观的认识。

什么是volatile

目前的操作系统大多数都是多CPU,当多线程对一个共享变量进行操作时,会出现数据一致性问题

Java编程语言允许线程访问共享变量,那么为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量,或者把这个变量声明成volatile,可以理解volatile是轻量级的synchronized。

使用volatile可以在Java线程内存模型确保所有线程看到这个变量的值是一致的,在多个处理器中保证了共享变量的“可见性”。

volatile两核心三性质

两大核心:JMM内存模型(主内存和工作内存)以及happens-before

三条性质:原子性,可见性,有序性

volatile性质

  1. 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(实现可见性)
  2. 禁止进行指令重排序。(实现有序性)
  3. 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。(不能实现原子性)
  4. volatile不会引起上下文的切换和调度

总结:volatile保证了可见性和有序性,同时可以保证单次读/写的原子性

相关的Cpu术语说明

什么是可见性?

在单核cpu的石器时代,我们所有的线程都是在一颗CPU上执行,CPU缓存与内存的数据一致性容易解决。因为所有线程都是操作同一个CPU的缓存,一个线程对缓存的写,对另外一个线程来说一定是可见的。

例如在下面的图中,线程A和线程B都是操作同一个CPU里面的缓存,所以线程A更新了变量a的值,那么线程B之后再访问变量 a,得到的一定是 a 的最新值(线程 A 写过的值)。

在多核CPU的时代,每颗 CPU 都有自己的缓存,这时 CPU 缓存与内存的数据一致性就没那么容易解决了,当多个线程在不同的CPU上执行时,这些线程操作的是不同的CPU缓存。比如下图中,线程A操作的是CPU-1上的缓存,而线程B操作的是CPU-2上的缓存,很明显,这个时候线程A对变量a的操作对于线程B而言就不具备可见性了。这个就属于硬件程序员给软件程序员挖的“坑”。

为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的值读到内部缓存(L1,L2或者其他)后再进行操作,但是操作完不知道何时再写回内存。

从上面的分析,我们可以知道,多核的CPU缓存会导致的可见性问题。

volatile是如何保证可见性的

代码语言:txt
AI代码解释
复制
instance = new Singleton();//instance是volatile变量

让我们来看看在处理器下通过工具获取JIT编译器生成的汇编指令来查看对volatile进行写操作的时候,cpu会做什么事?

转换成汇编代码如下:

file

有volatile修饰的共享变量进行写操作的时候会多出第二行汇编代码,也就是jvm会向处理器发送一条Lock前缀的指令,Lock前缀的指令在多核处理器下会引发两件事情:

  1. 将当前处理器缓存行的数据写回到系统内存
  2. 这个写回内存的操作会使在其他CPU缓存了该内存地址的数据无效,保证各个处理器的缓存是一致的 (通过一致性协议来实现的)

一致性协:每个处理器通过嗅探在总线上传播的数据来检查自己的缓存的值是否过期了,当处理器发现自己的缓存行对应的内存过期,在下次访问相同内存地址时,强制执行缓存填充,从系统内存中读取。

简单理解:volatile在其修饰的变量被线程修改时,会强制其他线程在下一次访问该变量时刷新缓存区。

volatile的两条实现原则
  1. Look 前缀指令会引起处理器缓存回写到内存。Lock 前缀指令导致在执行指令期间,声言处理器的LOCK#信号。在多处理器环境中,LOCK#信号确保在声言该信号期间,处理器可以独占任何共享内存。但是,在最近的处理器里,LOCK#信号一般不锁总线,而是锁缓存,毕竟锁总线开销的比较大,对干intel486和Pentiuln处理器,在锁操作时,总是在总线上声言LOCK#信号。但在P6和目前的处理器中,如果访问的内存区域已经缓存在处理器内部,则不会声言LOCK#信号。相反,它会锁定这块内存区域的缓存并回写到内存,并使用缓存一致性机制来确保修改的原子性,此操作被称为“缓存锁定”,缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据。
  2. 一个处理器的缓存回写到内存会导致其他处理器的缓存无效。IA-32 处理器和 Iniel 64 处理器使用 MESI (修改、独占、共享、无效)控制协议去维护内部缓存和其他处理器缓存的一致性。在多核处理器系统中进行操作的时候, IA-32和Intel64处理器能嗅探其他处理器访问系统内存和它们的内部缓存。处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致。例如,在 Pentium 和 P6famaly 处理器中,如果通过嗅探一个处理器来检测其他处理器打算写内存地址,而这个地址当前处干共享状态,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址时,强制执行缓存行填充

小结 Lock前缀的指令会引起处理器缓存写回内存; 一个处理器的缓存回写到内存会导致其他处理器的缓存失效; 当处理器发现本地缓存失效后,就会从内存中重读该变量数据,即可以获取当前最新值。

volatile是如何保证有序性

在解释有序性前,我们先来看看什么是指令重排?

导致程序有序性的原因是编译优化,指令重排序是JVM为了优化指令,提高程序运行效率,在不影响单线程程序执行结果的前提下,尽可能地提高并行度。但是在多线程环境下,有些代码的顺序改变,有可能引发逻辑上的不正确。有序性最直接的办法就是禁用缓存和编译优化,但是这样问题虽然解决了,我们的程序的性能就堪忧了,所以合理的方案是按需禁用缓存或者编译优化。

接下来我们来看一个著名的单例模式双重检查锁的实现

代码语言:txt
AI代码解释
复制
class Singleton {    private volatile static Singleton instance = null;    private Singleton() {    }    public static Singleton getInstance() {        if (instance == null) {                    //步骤1            synchronized (Singleton.class) {                if (instance == null)              //步骤2                    instance = new Singleton();    //步骤3            }        }        return instance;    }}

在以上代码中,instance不用volatile修饰时,输出的结果会是什么呢?我们的预期中代码是这样子执行的:线程A和B同时在调用getInstance()方法,线程A执行步骤1,发现instance为 null,然后同步锁住Singleton类,接着执行步骤2再次判断instance是否为null,发现仍然是null,然后执行步骤3,开始实例化Singleton。这样看好像没啥毛病,可是仔细一想,发现事情并不简单。 这时候,我们来我们先了解一下对象是怎么初始化的?

  • 对象在初始化的时候分三个步骤
代码语言:txt
AI代码解释
复制
memory = allocate();   //1、分配对象的内存空间ctorInstance(memory);  //2、初始化对象instance = memory;     //3、使instance指向对象的内存空间

程序为了优化性能,会将2和3进行重排序,此时执行的顺序是1、3、2,在单线程中,对结果是不会有影响的,可是在多线程程序下,问题就暴露出来了。这时候我们回到刚刚的单例模式中,在实例化的过程中,线程B走到步骤1,发现instance不为空,但是有可能因为指令重排了,导致instance还没有完全初始化,程序就出问题了。为了禁止实例化过程中的重排序,我们用volatile对instance修饰。

volatile内存语义如何实现

对于一般的变量则会被重排序(重排序分析编译器重排序和处理器重排序),而对于volatile则不能,这样会影响其内存语义,所以为了实现volatile的内存语义JMM会限制重排序。

其重排序规则如下:
  1. 如果第一个操作为volatile读,则不管第二个操作是啥,都不能重排序。这个操作确保volatile读之后的操作不会被编译器重排序到volatile读之前,其前面的所有普通写操作都已经刷新到主内存中;
  2. 如果第一个操作volatile写,不管第二个操作是volatile读/写,禁止重排序。
  3. 如果第二个操作为volatile写时,则不管第一个操作是啥,都不能重排序。这个操作确保volatile写之前的操作不会被编译器重排序到volatile写之后;
  4. 如果第二个操作为volatile读时,不管第二个操作是volatile读/写,禁止重排序

volatile的底层实现是通过插入内存屏障,但是对于编译器来说,发现一个最优布置来最小化插入内存屏障的总数几乎是不可能的,所以,JMM采用了保守策略。如下:

在每一个volatile读操作后面插入一个LoadLoad屏障,用来禁止处理器把上面的volatile读与后面任意操作重排序 在每一个volatile写操作前面插入一个StoreStore屏障,用来禁止volatile写与前面任意操作重排序 在每一个volatile写操作后面插入一个StoreLoad屏障,用来禁止volatile写与后面可能有的volatile读/写操作重排序 在每一个volatile读操作前面插入一个LoadStore屏障,用来禁止volatile写与后面可能有的volatile读/写操作重排序

保守策略下,volatile的写插入屏障后生成的指令示意图:

Storestore 屏障可以保证在volatile写之前,其前面的所有普通写操作已经对任意处理器可见了,Storestore 屏障将保障上面所有的普通写在volatile写之前刷新到主内存。

这里比较有意思的是, volatite 写后面的 StoreLoad 屏障的作用是避免volatile写与后面可能有的volatile 读/写操作重排序。

因为编译器常常无法准确判断在一个volatile写的后面是否需要插入一个StoreLoad屏障。为保证能正确实现volatile的内存语义,JMM在采取了保守策略,在每个volatile写的后面,或者在每个 volatile读的前面插入一个StoreLoad屏障。

保守策略下,volatile的读插入屏障后生成的指令示意图:

上面的内存屏障插入策略非常保守,在实际执行中,只要不改变volatile写-读的内存语义,编译器可根据情况省略不必要的屏障

举个例子:

代码语言:txt
AI代码解释
复制
public class Test {    int a ;    volatile int v1 = 1;    volatile int v2 = 2;    public  void readWrite(){        int i = v1;//第一个volatile读        int j = v2;//第二个volatile读        a = i+j://普通读        v1 = i+1;//第一个volatile写        v2 =j+2;//第二个volatile写    }    public synchronized void read(){        if(flag){            System.out.println("---i = " + i);         }    }}

针对readWrite方法,编译器在生成字节码的时候可以做到如下的优化:

注意:最后一个storeLoad屏障不能省略。因为第二个volatile写之后,方法立即return,此时编译器无法精准判断后面是否会有vaolatile读或者写。

如何正确使用volatile变量

在某些情况下,如果读操作远远大于写操作,volatile 变量可以提供优于锁的性能优势。

可是volatile变量不是说用就能用的,它必须满足两个约束条件:

  • 对变量的写操作不依赖于当前值。
  • 该变量没有包含在具有其他变量的不变式中。

第一个条件的限制使volatile变量不能用作线程安全计数器。虽然 i++ 看上去类似一个单独操作,实际上它是一个读取-修改-写入三个步骤的组合操作,必须以原子方式执行,而 volatile不能保证这种情况下的原子操作。正确的操作需要使i的值在操作期间保持不变,而volatile 变量无法做到这一点。

volatile和synchronized区别

  1. volatile比synchronized执行成本更低,因为它不会引起线程上下文的切换和调度
  2. volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  3. volatile只能用来修饰变量,而synchronized可以用来修饰变量、方法、和类。
  4. volatile可以实现变量的可见性,禁止重排序和单次读/写的原子性;而synchronized则可以变量的可见性,禁止重排序和原子性。
  5. volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
  6. volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

volatile和atomic原子类区别

  1. Volatile变量可以确保先行关系,即写操作会发生在后续的读操作之前
  2. 但是Volatile对复合操作不能保证原子性。例如用volatile修饰i变量,那么i++操作就不是原子性的。
  3. atomic原子类提供的atomic方法可以让i++这种操作具有原子性,如getAndIncrement()方法会原子性的进行增量操作把当前值加一,其它数据类型和引用变量也可以进行相似操作,但是atomic原子类一次只能操作一个共享变量,不能同时操作多个共享变量。

总结

总结一下volatile的特性

  • volatile可见性;对一个volatile的读,总可以看到对这个变量最终的写volatile有序性;JVM底层采用“内存屏障”来实现volatile语义volatile原子性;volatile对单个读/写具有原子性(32位Long、Double),但是复合操作除外,例如i++

如果你觉得文章还不错,你的转发、点赞、评论就是对我最大的鼓励。感谢您的阅读!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
华为Mate40/华为Mate40Pro忘记密码怎么解锁激活手机设备已锁定恢复出厂无法解锁账户ID屏幕锁解除刷机方法教程[通俗易懂]
今天带来一台用户华为Mate40Pro手机强制清除华为账号锁案例分享,这个台手机是用户公司手机,由于前使用者离职后未能退出手机的华为账号和锁屏密码,导致手机无法使用。
全栈程序员站长
2022/07/04
4.9K0
华为Mate40/华为Mate40Pro忘记密码怎么解锁激活手机设备已锁定恢复出厂无法解锁账户ID屏幕锁解除刷机方法教程[通俗易懂]
HUAWEI Mate40Pro解除账号忘记密码ID强制刷机鸿蒙系统激活锁能解开吗
第一步:将用户电脑USB镜像到我的电脑,进行USB1.0模式底层烧录。 第二步:底层烧录完成,成功获取临时权限,手机自动进入fastboot模式且读取手机系统版本:ELS-AN00 2.0.0.218。 第三步:fastboot模式切换 成功,读取手机相关信息,采用对应解锁方案。 第四步:手机信息读取成功,抓取手机OEM文件。 第五步:运行探索分析法分析OEM文件。 第六步:OEM分析成功并且修改OEM核心参数后,将解密参数进行烧录。 第七步:烧录完成,成功写入解密参数,执行删除华为ID指令。。 第八步:发送删除华为ID指令成功,成功删除华为ID,手机将自动重启。。 1)删除华为ID指令执行完成,所有操作执行完毕,手机将自动重启,初次重启设备,大概需要5-10分钟耐心等待开机。 2)手机重启后,按照系统引导激活手机。 3)按照系统引导激活手机。 4)成功进入桌面,服务结束。
全栈程序员站长
2022/07/02
4.1K0
HUAWEI Mate40Pro解除账号忘记密码ID强制刷机鸿蒙系统激活锁能解开吗
小米手机解BL锁、线刷详细教程,适用于小米全系列手机[通俗易懂]
[教程] 小米手机解BL锁、线刷详细教程,适用于小米全系列手机 这几天看到论坛里很多人在问怎么线刷,下面我就做个详细的线教程大家看一下高手别喷我哈 此教程只适合刷官方MIUI包 进入正题。 第一步:解BL锁 1.浏览器打开申请解锁小米手机点击立即解锁,然后再点击下载解锁工具,下载后保存到电脑也可以点击这里立即下载 2.解压后双击miflash_unlock.exe打开手机解锁工具V3.3
全栈程序员站长
2022/09/06
4.1K0
小米手机解BL锁、线刷详细教程,适用于小米全系列手机[通俗易懂]
iOS逆向(10)-越狱!越狱!远程连接登录手机
之前的九篇文章讲述的是在不越狱的情况下,详细的讲解了对APP重签名的原理,如何动态库注入,以及之后的各种调试技巧。这些功能其实已经很强大了,能够帮助咱们在绝大多数情况下去分析并且更改对方的APP了。这对付一些在开发过程中没有安全意识的APP其实已经足以。但是但凡对方有对APP进行防护,那么重签名就显得有些弱鸡了。
iOSSir
2019/06/14
2.2K0
iOS逆向(10)-越狱!越狱!远程连接登录手机
存储卡的使用方法大全
大家好,又见面了,我是你们的朋友全栈君。存储卡的使用方法大全 现在购买诺基亚手机,尤其是其智能手机的朋友是越来越多了,与其他品牌的机型相比,诺基亚的手机有一个最大的优点,就是支持储存卡内存扩充的机型比较多,这让大家在使用中不必再担心手机容量的问题,这也体现了诺基亚“科技以人为本”的宣传口号。今天,就为大家讲一讲适用于诺基亚手机存储卡的在日常使用中的一些操作方法,让大家在使用手机时能够更有效的操作它。 一、格式化 有很多网友会说“新买来的卡都要格式化”,其实这种说法并不正确,有的卡不用格式化即可使用。但是如果你还是想要格式化储存卡,那么我要告诉你最好是使用手机进行格式化,不过有一点要注意:由于手机本身的CPU速度和接口的限制,格式化卡的速度较慢,所以一定要保持手机的电量充足。一般来看,512M的卡格式化一次大约要10分钟,所以手机的电量应该尽量保持在至少3格! 有的时候手机格式化会失败,这个时候先不要下结论说卡坏了,你可用电脑再次格式化一次,但是格式化的“格式”一定要选择“FAT”,否则格式化后的卡是不能被手机识别的。如果电脑也不能格式化,可以再使用“MMCMedic”这个软件进行一次修复。这个软件适用于MMC和RS-MMC卡,不能用于SD卡。不过SD卡的修复相对比较简单,可以使用PDA或者数码相机进行格式化就可以了。 二、储存卡修复 在格式化以后,有的卡会出现不能使用或者使用过程中会出现种种错误,这时可以使用电脑系统里的“磁盘工具”进行修复。连接读卡器,然后右键点击存储卡所在的盘符,选择“属性-查错”,然后再选择“自动修复文件错误”和“扫描并试图恢复坏扇区”,不过所用的时间可能较长,所以要有一定的耐心。 三、卡内数据恢复 当误删除或者误格式化存储卡以后,只要没有再次输入数据,一般都可以恢复卡里面的数据资料。如果已经输了新文件,有时候也可以恢复部分的卡内原数据,这个主要是要视所新存入文件的大小而定。具体操作如下:我们需要的工具是电脑、读卡器和EasyRecovery软件。 首先,连接读卡器,打开EasyRecovery,选择“数据修复”菜单,根据你的情况选择相应的选项,比如“恢复已删除的文件”。 第二步,软件会要求扫描系统驱动器。稍候,显示驱动器后,选择“全面扫描”,如果没有出现存储卡,则需重新连接读卡器。 第三步,扫描完成后,出现目录恢复选项,可根据资料存储的具体情况选择。比如选择MMC(这个一般是存储卡的名字),以后的过程就是软件傻瓜式的操作了^_^。相信操作到这一地步,大家都会清楚了,简单地说就是选择电脑上的一个文件夹存放恢复的数据。 诺基亚DKU-2插头引脚定义公布!
全栈程序员站长
2022/09/08
3.3K0
基于 RK3588 的 ARM 架构 ITX 主机搭建指南:系统选型和配置优化
这篇文档,应该是目前你能够找到的 RK3588 相关,最全面的设备系统选型和配置优化的内容了,希望能够帮到有类似需求的你。
soulteary
2025/04/07
3250
基于 RK3588 的 ARM 架构 ITX 主机搭建指南:系统选型和配置优化
linux基础命令大全及使用方法
RAID 0又称为Stripe或Striping,它代表了所有RAID级别中最高的存储性能。RAID 0提高存储性能的原理是把连续的数据分散到多个磁盘上存取,这样,系统有数据请求就可以被多个磁盘并行的执行,每个磁盘执行属于它自己的那部分数据请求。这种数据上的并行操作可以充分利用总线的带宽,显著提高磁盘整体存取性能。
用户3557781
2019/06/12
4.6K0
linux基础命令大全及使用方法
硬件资料和软件资料_电脑硬件检测工具哪个好
2. BIOS报警声意义 3. BIOS自检与开机故障相关问题 5. 计算机几个常见指标的意义 6. 显卡GPU参数 7. 显示卡常见故障全面解决 8. 集成声卡常见故障及解决 9. 显示器经典故障以及处理办法 10. AMI主板代码大全(BIOS-ID)
全栈程序员站长
2022/11/01
4.8K0
大疆无人机安全与DroneID漏洞
消费级无人机可以用于高级航拍、物流和人道主义救援等等。但是其广泛使用给安全、安保和隐私带来了许多风险。例如,攻击方可能会使用无人机进行监视、运输非法物品,或通过侵入机场上方的封闭空域造成经济损失。为了防止恶意使用,无人机制造商采用多种对策来强制安全可靠地使用无人机,例如对速度和高度施加软件限制,或使用地理围栏实施禁飞区。
CDra90n
2023/06/24
3.3K2
大疆无人机安全与DroneID漏洞
常用电脑资料速查
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/10
2.5K0
万字长文|大数据学前准备之Linux入门笔记(附资料)
对于大数据学习而言,Linux运维可以说是必备的技能。可以不研究的过于高深,但是基本的操作和使用一定要熟练。Linux的学习需要大量的实践,本文从linux的基本知识,实战操作,到常用的指令与软件安装等都有总结。
大数据流动
2021/09/28
8100
WEB服务器攻击类型和应对方案
肉鸡也称傀儡机,是指可以被黑客远程控制的机器。比如用"灰鸽子"等诱导客户点击或者电脑被黑客攻破或用户电脑有漏洞被种植了木马,黑客可以随意操纵它并利用它做任何事情。
星哥玩云
2022/05/28
1180
WEB服务器攻击类型和应对方案
软件测试之安全怎么做?
扫描?在很多人的眼中,做安全的就是整天拿个工具在哪里做扫描操作,使用各种不同的工具做扫描。是的,扫描是安全测试的很重要的一部分,扫描可以快速有效的发现问题。扫描工具的易用性、方便性决定了重要地位。但是扫描工具的局限性、程序的不够灵活等缺点也是显而易见的。不管是扫描报告的分析、漏洞的深度挖掘、测试的组织等等的工作都离不开安全测试人员,所以只能说扫描工具减轻了测试人员的工作量,是安全测试的一种手段。
小黑同学
2020/08/17
2.3K0
面试题丨android面试问题合集
静态分析工具是指在不运行程序的情况下,通过对程序文件进行源代码分析,从而对程序的安全性、可靠性、性能等进行分析的工具。它可以识别出程序文件中的漏洞,但只能识别出程序文件中的静态漏洞,不能识别出程序在运行中可能出现的动态漏洞。比如apktool、androidkiller、jeb,GDA、smali、jadx等
极安御信安全研究院
2023/06/08
2.4K1
面试题丨android面试问题合集
Android Automotive Framework调试技巧
三次握手只是一个数据传输的过程,但是,我们传输前需要一些准备工作,比如将创建一个套接字,收集一些计算机的资源,将一些资源绑定套接字里面,以及接受和发送数据的函数等等,这些功能接口在一起构成了socket的编程
wizzie
2022/12/22
5.5K0
Android Automotive Framework调试技巧
❤️肝下25万字的《决战Linux到精通》笔记,你的Linux水平将从入门到入魔❤️【建议收藏】
因为AT&T(通用电气)的政策改变,在Version 7 Unix推出之后,发布新的使用条款,将UNIX源代码私有化,在大学中不再能使用UNIX源代码。Andrew S. Tanenbaum(塔能鲍姆)教授为了能在课堂上教授学生操作系统运作的实务细节,决定在不使用任何AT&T的源代码前提下,自行开发与UNIX兼容的操作系统,以避免版权上的争议。他以小型UNIX(mini-UNIX)之意,将它称为MINIX。
全栈程序员站长
2022/09/05
2.4K0
❤️肝下25万字的《决战Linux到精通》笔记,你的Linux水平将从入门到入魔❤️【建议收藏】
Java面试:备战22k
特别说明:别纠结于薪资能不能到22k,在到达22k之前,这些博文里的专业技能方面都要懂吧,如果连这些基础的东西都不懂,你到了22k,估计也是很水的存在了。除此之外,拿22薪你还需要具备,能独立完成一个复杂模块的需求分析、方案设计和最终落地实现,寻找更优的设计和解决方案,积极优化慢 SQL、慢服务,具备排查问题的能力,遇到线上问题能及时定位和修复上线,例如:数据库死锁、服务器宕机、服务器 Full GC 频繁等。合理分配需求,做好进度把控、风险评估、Code Review。
Java廖志伟
2021/04/07
1.2K0
Java面试:备战22k
springcloudAlibaba&rancher【后端专题】
DevOps即Development和Operations的组合词,是一组过程、方法与系统的统称,用于促进开发应用程序或软件工程、技术运营和质量保障QA部门之间的沟通、协作与整合。
高大北
2022/12/20
2.4K0
springcloudAlibaba&rancher【后端专题】
springcloudAlibaba+devops
springcloudAlibaba&rancher【后端专题】 简介:用户增长的数据分析模型AARRR
高大北
2022/12/20
1.4K0
springcloudAlibaba+devops
数据中心机房建设方案
数据中心机房总面积大约178平方米,使用面积约为123平方米,分为三个功能区域,分别为主设备机房、动力机房、操作间、钢瓶间。各间需要单独隔开。隔开后主设备机房用于放置配线柜、机柜、服务器、小型机、网络设备、通讯设备等重要设备;动力机房放置UPS、电池、配电柜等。
全栈程序员站长
2022/08/22
2.8K0
数据中心机房建设方案
推荐阅读
相关推荐
华为Mate40/华为Mate40Pro忘记密码怎么解锁激活手机设备已锁定恢复出厂无法解锁账户ID屏幕锁解除刷机方法教程[通俗易懂]
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档