首页 > 编程知识 正文

java transient关键字,java字节码文件的后缀是什么

时间:2023-05-05 13:51:36 阅读:148597 作者:537

内存相关概念计算机在执行程序时,各指令由CPU执行,但执行指令时,必然涉及数据的读写。 由于程序执行中的暂时数据被储存在主存储器(物理存储器)中,所以CPU的执行速度很快,但是从存储器的数据的读取和写入与CPU执行指令的速度相比非常慢,所以无论何时只要在与存储器的交换中进行对数据的操作因此,CPU有高速缓存

也就是说,如果在程序执行过程中将运算所需的数据从主存储器复制到CPU的高速缓存中,则CPU在计算时直接从该高速缓存读出数据或向其写入数据,在运算结束后,将高速缓存的数据闪存到主存储器中举个简单的例子吧。 例如,下面的代码。

i=i 1; 1单线程:当线程执行此语句时,它首先从主内存读取I值并将其复制到高速缓存中。 然后,CPU执行指令,将I加1,然后将数据写入高速缓存,最后将高速缓存中I的最新值刷新到主存储器。 没有任何问题。

多线程:多核CPU每个线程都有自己的缓存,因为每个线程可能在不同的CPU上运行。 (单核CPU实际上也会出现这种问题,但它将以线程计划的形式单独运行。 本文以多核CPU为例。 例如,如果两个线程同时执行此代码,则如果初始I的值为0,则希望在执行两个线程后I的值为2。 但是事实会变成这样吗?

这些情况包括:

初始时,两个线程分别读取i的值存入各自所在的CPU的高速缓存当中,然后线程1进行加1操作,然后把i的最新值1写入到内存。此时线程2的高速缓存当中i的值还是0,进行加1操作之后,i的值为1,然后线程2把i的值写入内存。最终结果i的值是1,而不是2。

这就是有名的缓存一致性问题。 通常,访问这类多个线程的变量称为共享变量

这意味着,如果一个变量中有多个CPU存在高速缓存,则可能会出现通常在多线程编程过程中出现的高速缓存不一致问题。

解决缓存不一致问题通常有以下两种解决方法:

以总线加锁的方式通过高速缓存一致性协议的两种方式都是硬件级提供的方式。

早期的CPU通过在总线上放置LOCK#锁来解决缓存不一致问题。 由于CPU与其他部件之间的通信是通过总线进行的,因此对总线施加LOCK#锁定会阻止其他CPU对内存等其他部件的访问,从而只有一个CPU可以使用该变量的内存。 例如,在上面的例子中,如果某个线程正在执行i=i 1,在执行该代码的过程中在总线上发出了LCOK锁定的信号,则在等待该代码完全执行之后,其他CPU从具有变量I的存储器中读取变量,并进行相应的操作这将解决缓存不一致问题。

但是,上述方法存在效率低下的问题,因为在锁定总线时,其他CPU无法访问内存。

因此,出现了缓存一致性协议。 最有名的是Intel的MESI协议,MESI协议可以确保每个缓存中使用的共享变量的副本是一致的。 其核心思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为++无效状态++,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。

violate关键字(2.3 )容易变得不稳定。

使用violate声明变量时,表示虚拟机很可能会被某些程序或线程更改。 更改此变量后,为了使APP应用程序中的其他线程能够看到此更改,虚拟机必须采取特殊措施来确保此变量的可见性等特征。

violate的缺点violate不能保证与操作相符的原子性。 每次线程使用变量时,由volatile限定的变量都会读取变量更改的最高值。 volatile容易被误用,用于原子操作。

violate Java运行时具有名为jvm虚拟机堆栈的内存区域,每个线程的运行时都有一个线程堆栈。 线程堆栈包含线程运行时变量的值信息。 当线程访问某个对象时,它首先通过对对象的引用找到堆内存中的变量值,然后将堆内存变量的特定值加载到线程本地存储器中以创建变量的副本。 然后,线程直接修改副本变量的值,而与对象的堆内存变量值无关,并在修改后的某个时间点(线程结束之前)自动将线程变量副本的值写回到堆变量中。 这将更改堆中对象的值。 下图显示了此写操作的交互。

read and load将变量从主存储器复制到当前工作存储器use and assign并执行代码,更改共享变量值store and write,用工作存储器数据更新主存储器相关内容。 use and assign可能会多次出现,但这些操作不是原子的。 也就是说,read load后,主存储器count变量发生变更后,存储在线程的工作存储器中

出来的结果会和预期不一样。对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的。

例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6,线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6。导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。

使用

用一个线程来控制开关变量,通知其他线程的开关闭合情况。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。