openjdk,如果华为鸿蒙系统是真的且兼容安卓应用apk的话?
我的回答最专业
之一,华为的系统,就是重新写了一个比安卓更高效的另外一个安卓,不是在安卓上改,是从设计,效率,扩展等方面完全重构。
第二,因为是重新写的,因此不涉及版权等问题。支持安卓App,并不是什么问题,目前安卓是边翻译边运行,所以卡顿,华为思路是全部编译成系统语言再执行,效率高很多。
第三,安卓的设计思路比较落后了,谷歌自己都意识到了,所以它自己也会抛弃安卓系统。新开发的有没有华为高效是另外一个话题。
斗胆说一句,其实华为很多手机,应该已经用了自己的系统,内核已经是华为的了,只是没有公开说。用户其实已经用了很久了。比如数码变焦50倍,别人为啥做不出来?因为基于安卓系统,需要大量计算填补点之间的空间,没有Ai芯片,基于安卓系统是做不到的。所以,其实很多厂家都看出来门道。对于华为,用智能芯片加优化的系统,可以简单实现。而别人可以尝试下,不管是不是电脑画的,你就画不出来。
openjdk和普通jdk有什么区别?
jdk这个是sun公司开发的,据说要收费的,openjdk是阿里开发的目前免费!
如何彻底理解volatile关键字?
谢谢邀请~!下面从 用法、注意事项、底层原理进行说明!
JMM 基础-计算机原理Java 内存模型即Java Memory Model,简称JMM,JMM定义了Java 虚拟机(JVM)在计算机(RAM) 中的工作方式。 JVM 是整个计算机虚拟模型,所以JMM是隶属于JVM的,
在计算机系统中,寄存器是L0级缓存,接着依次是L1,L2,L3(接下来是内存,本地磁盘,远程存储).越往上的缓存存储空间越小,速度越快,成本也越高。越往下的存储空间越大,速度更慢,成本也越低。
从上至下,每一层都都可以是看作是更下一层的缓存,即:L0寄存器是L1一级缓存的缓存,
L1是L2的缓存,一次类推;每一层的数据都是来至于它的下一层。
在现在CPU上,一般来说L0,L1,L2,L3都继承在CPU内部,而L1还分为一级数据缓存和一级指令缓存,分别用于存放数据和执行数据的指令解码,每个核心拥有独立的运算处理单元、控制器、寄存器、L1缓存、L2 缓存,然后一个CPU的多个核心共享最后一层CPU缓存L3。
CPU 的缓存一致性解决方案分为以下两种方案
总线锁(每次锁总线,是悲观锁)
缓存锁(只锁缓存的数据)
MESI协议如下:
M(modify):I(invalid)E(Exclusive)S(Share)JMM内存模型的八种同步操作1、read(读取),从主内存读取数据
2、load(载入):将主内存读取到的数据写入到工作内存
3、use(使用): 从工作内存读取数据来计算
4、assign(赋值):将计算好的值重新赋值到工作内存中
5、store(存储):将工作内存数据写入主内存
6、write(写入):将store过去的变量值赋值给主内存中的变量
7、lock(锁定):将主内存变量加锁,标识为线程 独占状态
8、unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量
Java 内存模型带来的问题1、可见性问题
左边CPU中运行的线程从主内存中拷贝对象obj到它的CPU缓存,把对象obj的count变量改为2,但这个变更对运行在右边的CPU中的线程是不可见,因为这个更改还没有flush到主内存中。
在多线程环境下,如果某个线程首次读取共享变量,则首先到主内存中获取该变量,然后存入到工作内存中,以后只需要在工作内存中读取该变量即可,同样如果对该变量执行了修改的操作,则先将新值写入工作内存中,然后再刷新至于内存中,但是什么时候最新的值会被刷新到主内存中是不太确定的,一般来说是很快的,但是具体时间未知,,要解决共享对象可见性问题,我们可以使用volatile关键字或者加锁。
2、竞争问题
线程A 和 线程B 共享一个对象obj, 假设线程A从主存读取obj.count变量到自己的缓存中,同时,线程B也读取了obj.count变量到它的CPU缓存,并且这两个线程都对obj.count做了加1操作,此时,obj.count加1操作被执行了两次,不过都在不同的CPU缓存中。
如果则两个加1操作是串行执行的,那么obj.count变量便会在原始值上加2,最终主内存中obj.count的值会为3,然后图中两个加1操作是并行的,不管是线程A还是线程B先flush计算结果到主存,最终主存中的obj.count只会增加1次变成2,尽管一共有两次加1操作,要解决上面的问题我们可以使用synchronized 代码块。
3、重排序
除了共享内存和工作内存带来的问题,还存在重排序的问题,在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。
重排序分3中类型:
(1) 编译器优化的重排序。
(2) 指令级并行的重排序
(3)内存系统的重排序
① 数据依赖性
数据依赖性: 如果两个操作访问同一变量,且这两个操作中有一个为写,此时这两个操作之间就存在数据依赖性。
依赖性分为以下三种:
上图很明显,A和C存在数据依赖,B和C也存在数据依赖,而A和B之间不存在数据依赖,如果重排序了A和C或者B和C的执行顺序,程序的执行结果就会被改变。
很明显,不管如何重排序,都必须保证代码在单线程下的运行正确,连单线程下都无法保证,更不用讨论多线程并发的情况,所以就提出一个as - if -serial 的概念。
4、as - if -serial
意思是:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as - if -serial 语义。
A和C之间存在数据依赖,同时B和C之间也存在数据依赖关系,因此在最终执行的指令序列中,C不能被重排序A和B的前面(C排到A和B的前面,程序的结果将会被改变)。但A和B之间没有数据依赖关系,编译器和处理器可以重排序A和B之间的执行顺序。
as - if -serial 语义把单线程程序保护了起来,遵守as-if-serial语义的编译器、runtime和处理器可以让我们感觉到: 单线程程序看起来是按程序的顺序来执行的。as-if-srial语义使单线程程序无需担心重排序干扰他们,也无需担心内存可见性的问题。
5、内存屏障
Java 编译器在生成指令序列的适当位置会插入内存屏障来禁止特定类型的处理去重排序,从而让程序按我们预想的流程去执行。
① 保证特定操作的执行顺序
② 影响某些数据(或者是某条指令的执行结果)的内存可见性
编译器和CPU能够重排序指令,保证最终相同的结果,尝试优化性能。插入一条Memory Barrier 会告诉编译器和CPU ,不管什么指令都不能和这条Memory Barrier 指令重排序。
Memory Barrier 所做的另外一件事是强制刷出各种CPU cache, 如一个Write-Barrier(写入屏障)将刷出所在的Barrier 之前写入cache的数据,因此,任何CPU上的线程都能读取到这些数据的最新版本。
JMM把内存屏障指令分为4类:
StoreLoad Barriers 是一个"全能型"的屏障,它同时具有其他3个屏障的效果,
volatile 关键字介绍1、保证可见性
对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写。
我们先看下面代码:
initFlag 没有用volatile关键字修饰;
上面结果为:
说明一个线程改变initFlag状态,另外一个线程看不见;
如果加上volatile关键字呢?
结果如下:
我们通过汇编看下代码的最终底层实现:
volatile写的内存语义如下:
当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。
当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
比如:
如果我们将flag变量以volatile关键字修饰,那么实际上:线程A在写flag变量后,本地内存A中被线程A更新过的两个共享变量的值都被刷新到主内存中。
在读flag变量后,本地内存B包含的值已经被置为无效。此时,线程B必须从主内存中读取共享变量。线程B的读取操作将导致本地内存B与主内存中的共享变量的值变成一致。
如果我们把volatile写和volatile读两个步骤综合起来看的话,在读线程B读一个volatile变量后,写线程A在写这个volatile变量之前所有可见的共享变量的值都将立即变得对读线程B可见。
2、原子性
volatile 不保证变量的原子性;
运行结果如下:
因为count ++;
包含 三个操作:
(1) 读取变量count
(2) 将count变量的值加1
(3) 将计算后的值再赋给变量count
从JMM内存分析:
下面从字节码分析为什么i++这种的用volatile修改不能保证原子性?
javap : 字节码查看
其实i++这种操作主要可以分为3步:(汇编)
读取volatile变量值到local增加变量的值把local的值写回,让其它的线程可见Load到store到内存屏障,一共4步,其中最后一步jvm让这个最新的变量的值在所有线程可见,也就是最后一步让所有的CPU内核都获得了最新的值,但中间的几步(从Load到Store)是不安全的,中间如果其他的CPU修改了值将会丢失。
3、有序性
(1) volatile重排序规则表
① 当第二个操作是volatile写时,不管之一个操作是什么,都不能重排序。这个规则确保volatile写之前的操作不会被编译器重排序到volatile写之后。
② 当之一个操作是volatile读时,不管第二个操作是什么,都不能重排序。这个规则确保volatile读之后的操作不会被编译器重排序到volatile读之前。
③ 当之一个操作是volatile写,第二个操作是volatile读时,不能重排序。
(2) volatile的内存屏障
① volatile写
storestore屏障:对于这样的语句store1; storestore; store2,在store2及后续写入操作执行前,保证store1的写入操作对其它处理器可见。(也就是说如果出现storestore屏障,那么store1指令一定会在store2之前执行,CPU不会store1与store2进行重排序)
storeload屏障:对于这样的语句store1; storeload; load2,在load2及后续所有读取操作执行前,保证store1的写入对所有处理器可见。(也就是说如果出现storeload屏障,那么store1指令一定会在load2之前执行,CPU不会对store1与load2进行重排序
② volatile读
在每个volatile读操作的后面插入一个LoadLoad屏障。在每个volatile读操作的后面插入一个loadstore屏障。
loadload屏障:对于这样的语句load1; loadload; load2,在load2及后续读取操作要读取的数据被访问前,保证load1要读取的数据被读取完毕。(也就是说,如果出现loadload屏障,那么load1指令一定会在load2之前执行,CPU不会对load1与load2进行重排序)
loadstore屏障:对于这样的语句load1; loadstore; store2,在store2及后续写入操作被刷出前,保证load1要读取的数据被读取完毕。(也就是说,如果出现loadstore屏障,那么load1指令一定会在store2之前执行,CPU不会对load1与store2进行重排序)
volatile的实现原理volatile的实现原理
❶ 通过对OpenJDK中的unsafe.cpp源码的分析,会发现被volatile关键字修饰的变量会存在一个“lock:”的前缀。
❷ Lock前缀,Lock不是一种内存屏障,但是它能完成类似内存屏障的功能。Lock会对CPU总线和高速缓存加锁,可以理解为CPU指令级的一种锁。
❸ 同时该指令会将当前处理器缓存行的数据直接写会到系统内存中,且这个写回内存的操作会使在其他CPU里缓存了该地址的数据无效。
❹ 具体的执行上,它先对总线和缓存加锁,然后执行后面的指令,最后释放锁后会把高速缓存中的脏数据全部刷新回主内存。在Lock锁住总线的时候,其他CPU的读写请求都会被阻塞,直到锁释放。
【欢迎随手关注@码农的一天,希望对你有帮助】
Ubuntu?
Canonical于今天正式宣布:即将到来的Ubuntu 19.10 (Eoan Ermine) 发行版本目前已经进入Final Freeze开发阶段,要比路线图上的10月17日提前了几天时间。Ubuntu 19.10发行版于10月10日正式进入Final Freeze,这是开发过程中的最后阶段,除非ISO镜像或者安装程序中发现严重BUG否则不会停止下来。候选发布镜像目前已经开放测试,以确保新版本的平稳和流畅发布。
Adam Conrad表示:“一旦存档和proposed-migration得到解决,我们将会在周五晚上或者周六上午关闭cronjobs并分享一些候选镜像,我们希望所有参与测试的用户对某个(或者两个)风味版本感兴趣,并且能够体验数小时,从而确保我们能够在下周发布的正式版本中能够流畅升级。”
名为Eoan Ermine的Ubuntu 19.10操作系统将于10月17日到来,它具有许多新功能和更新的组件,其中我们可以提及最新的GNOME 3.34桌面环境,具有用于initramfs的LZ4压缩算法的Linux 5.3内核系列,以及在其中的实验性ZFS支持。安装程序,LibreOffice 6.3办公套件,PulseAudio 13.0声音系统和Firefox 69 Web浏览器。
在后台方面,Ubuntu 19.10发行版本搭载了GCC 9.2.1,Glibc 2.30,Python 3.7.5,Ruby 2.5.5,PHP 7.3.8,Perl 5.28.1,Golang 1.12.10,OpenJDK 11,QEMU 4.0,dpdk 18.11.2,libvirt 5.6, Open vSwitch 2.12, OpenStack Train和Rustc 1.37. AArch64和POWER工具链已启用,可以针对ARM,S390X和RISCV64体系结构进行交叉编译。
Ubuntu 19.10还具有对最新的Raspberry Pi 4 Model B单板计算机的开箱即用支持,以及特定于Nvidia的增强功能,例如在使用Nvidia图形驱动程序时具有更好的启动可靠性,该驱动程序现在包含在ISO映像中。默认设置,以及专门针对Nvidia GPU的渲染平滑度和帧速率改进。
jdk和oracle?
JDK和OpenJDK的区别
1.授权协议的不同
OpenJDK采用GPL V2协议发布,而JDK则采用JRL协议发布。两个协议虽然都是开放源代码的,但是在使用上的不同在于GPL V2允许在商业上使用,而JRL只允许个人研究使用。
2.OpenJDK只包含最精简的JDK
OpenJDK不包含其他的软件包,比如Rhino Java DB JAXP……,并且可以分离的软件包也都是尽量的分离,但是这大多数都是自由软件,你可以自己下载加入。
3.OpenJDK源代码不完整
这个很容易想到,在采用GPL协议的OpenJDK中,SUN JDK的一部分源代码因为产权的问题无法开放OpenJDK使用,其中最主要的部分就是JMX中的可选元件SNMP部分的代码。
因此这些不能开放的源代码将它作成plug,以供OpenJDK编译时使用,你也可以选择不要使用plug。
而Icedtea则为这些不完整的部分开发了相同功能的源代码(OpenJDK6),促使OpenJDK更加完整。
4.OpenJDK和IcedTea的关系
IcedTea项目最初是由于OpenJDK不完整(因产权 而造成的障碍)而创立的,社区需要一个完整的开源工具链及代码库。
IcedTea长期以来一直是OpenJDK的一套补丁,正如刚才我所说到的,它有一个 基于“./configure”的不同的构建系统。
在OpenJDK中,我们已经替换了产权代码(encumbered code),因此不再有障碍了。正因为我们的努力,IcedTea项目已经减少了使用补丁的数量。
IcedTea中看上去不错的一点是,它的 configure脚本使得在多种不同的模式下构建OpenJDK变得很容易,比如使用Zero Assembler Port在非x86/sparc芯片上来支持编译等等。
IcedTea提供的一大块内容是plugin/Java-web-start基础架构。
5.部分源代码用开源代码替换
由于产权的问题,很多是SUN JDK的源代码被替换成一些功能相同的开源代码,比如说字体栅格化引擎,使用Free Type代替。
6.不能使用Java商标
这个很容易理解,在安装OpenJDK的机器上,输入“java -version”显示的是OpenJDK,但是如果是使用Icedtea补丁的OpenJDK,显示的是java。(未验证)