volatile关键字学习回顾(1)

3 篇文章 0 订阅
1 篇文章 0 订阅

最近在学习多线程相关的知识,volatile关键字以前只知道是保证线程间可见,被volatile关键字修饰的变量可以保证线程间及时看到,并没有深入了解过,在此对volatile从硬件层面到jvm层面做出深层次挖掘分析。

volatile的作用

1:volatile的作用是保证共享变量的可见性,不能保证原子性,也不能完全的保证线程安全(why不能保证会在后续给出答案)

2:volatile的作用是保证线程在同一时间读到变量的值是一致的

3:如果某个线程对volatile修饰的共享变量做出更新,那么其他线程会第一时间看到更新

硬件系统架构

硬件系统架构演进

计算机运行时,每条指令都在cpu中运行,在执行过程中势必会涉及到读写(load与store)。

程序的指令存在内存中,这时就存在一个问题

内存的读写速度跟不上cpu的运行速度

如下就有那些大厂的大神做出了以下改进

搞了一个Cpu高速缓存,cpu高速缓存为每一个cpu独有,只与在该cpu运行的线程有关

 

其实主要了解到就是有高速缓存区这么个东西,它存在的意义就是避免了cpu直接打交道,而且告诉缓存区存在L1,L2,L3....Ln这么多的分级高速缓存区,其中L1的速度最快,以此往上Ln+1为Ln缓存数据做同步数据,以此来充分激发CPU的性能。

然后解下来会产生一下问题:load是解决了,如何将数据写入?

缓存分布在每个cpu中,如何保证在多核运行结束后,保证cpu将执行结果正确的拼接起来,也就是保持缓存数据一致呢?

一般写入方法分为两种:

1:直写(write-through)

直写可以理解成直接透过本CPU独有的缓存,直接写到内存中,如果有其他CPU已经把内存中数据更新写入了,那么会更新已经被修改的数据。
2:回写(write-back)

缓存不会把写操作传递到下一级(内存)中,而是先修改cpu独有的缓存区域中的数据,并把对应的缓存数据定义为“脏”数据。脏数据会继续触发回写,就是Ln-1会回写到Ln那个层级的高速缓存中,直到回写到内存中,回写后,“脏”数据就变干净了。

当一个脏数据被丢弃时,总要进行一次回写

缓存一致性问题

举个栗子

i++;

当线程运行这段代码时,

1:首先从主内存读取i=1

2:然后copy一份到cpu高速缓存区,然后cpu执行+1操作

3:然后将结果写入高速缓存区中,触发回写一直到主内存中

此时在单线程没有问题,但是如果同时开启多个线程会怎样?

如果同时存在多个线程A,B同时执行i++,正常来讲应该是3,但事实是怎样的?大力分析来一波

1:A从主内存中取到值i=1,此时运行i++,将结果回写到主内存中,此时i==2;

2:B做同样的事情,再次把i赋值为2;

3:与结果不符。

这个就是缓存一致性的问题

解决缓存一致性问题

1:在总线长加LOCK#锁(此种方式比较蠢,相当于把所有操作都放在了单线程)

2:通过缓存一致性解决

缓存一致性协议

在多核CPU中,每个CPU核心都有一级缓存,二级缓存等

这样一来就需要当多个CPU核心在处理写操作时,需要保持共享数据资源的其他CPU的可见性/一致性

而窥探技术与MESI技术的出现就是为了解决多核CPU时代缓存不一致问题

窥探技术:

窥探技术就是把所有CPU的数据传输放到一条共享的总线上,所有CPU都能看到这条总线。

高速缓存本身是独立的,但是内存是共享的,所有缓存往内存中写的操作,都需要经过仲裁,同一个指令周期内,只有一个缓存可以读写内存。

而窥探技术的思想就是:缓存不仅仅是在与内存读写操作时候才和总线打交道,而是在不停的窥探总线上的数据交换,跟踪其他缓存在做什么。

so,当一个缓存代表他所属的CPU去读写内存时,其他CPU都会得到通知,以此来使自己的缓存块保持同步,只要某个CPU开始写内存,其他CPU就会知道自己的所存的数据已经失效了。

MESI协议

缓存系统操作的最小单位就是缓存行

  1. 失效(invalid)缓存行:该cpu缓存中无该缓存行,或者缓存中的缓存行已经失效了。
  2. 共享(shared)缓存行:缓存行的内容使同主内存内容保持一致的一份拷贝,这种状态的缓存行 只能读取,无法写入。
  3. 独占(exclusive)缓存行:和共享缓存行一样,当前的缓存行也是缓存行的一份copy,只不过当从s状态转入到E状态以后,其他缓存中的缓存行将没有办法持有原有缓存行,这时候其他缓存中的缓存行将变为失效(I)状态.
  4. 已修改(Modified)缓存行:这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中

只有当缓存行处于E或M状态时,CPU才能去写它,
也就是说只有这两种状态下,CPU是独占这个缓存行的。
当CPU想写某个缓存时,如果它没有独占权,它必须先发送一-条 “我要独占权”的请求给总线, 这会通知其他CPU,把它们拥有的同一缓存行的拷贝失效(I状态)。
只有在获得独占权后,CPU才能开始修改数据。并且此时,这个CPU知道,
这个缓存行只有一份拷贝,在我自己的缓存里,所以不会有任何冲突。
反之如果有其他CPU想读取这个缓存行(我们马上能知道,因为我们一直在窥探总线) , 独占或已修改的缓存行必须先回到“共享”状态。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值