并发编程(八)----volatile关键字

volatile的作用

  • 保证共享变量的可见性,不能保证原子性,也不能保证线程安全
  • 确保所有线程在同一时刻读取到的共享变量的值是一致的
  • 如果某个线程对volatile修饰的共享变量进行更新,那么其他线程可以立刻看到这个更新

硬件系统架构

硬件系统架构演进

  • 1.计算机在运行程序时,每条指令都是在CPU中进行的,在执行过程中势必会涉及到数据的读写。程序运行的数据是存储在主内存中,这时就会有一个问题:读写主内存的数据没有CPU执行指令的速度快,如何任何一个交互都需要与主内存打交道则会大大降低CPU效率。
    解决问题的办法:CPU告诉缓存诞生,CPU高速缓存为某个CPU独有,只与在该CPU运行的线程有关
  • 2.现代CPU为了提高访问数据的效率,在每个CPU核心上都会有多级容量小,速度快的缓存,(分别成为L1Cache,L2Cache,多核心共享L3Cache等),用于缓存常用的数据。
    缓存系统中是以缓存行(cache line)为单位存储的。缓存行是2的整数幂个连续字节,一般为32-256个字节。最常见的缓存行大小是64个字节。
    因此CPU在执行一条度内存指令时,它是会将内存地址所在的缓存行大小的内容都加载进缓存中的,也就是一次加载一整个缓存行。
  • 3.CPU首先使用自己的寄存器,然后使用速度更快的L1缓存。
  • 4.CPU为了避免直接与主内存打交道,与速度比主内存高出很多的CPU高速缓冲区打交道,充分利用了CPU的高性能。
  • 5.CPU读取速度是够快了,问题是,CPU完成操作后,如何将数据写入?
    缓存分布在每个CPU中,如何保障写入后的数据与各个CPU之间的缓存保持数据一致?
  • 6.直写-透过本级缓存,直接把数据写到下一级缓存(或直接到内存)中,如果对应的数据被缓存了,我们同时更新缓存中的内容(甚至直接丢弃)。所以,直写时缓存行永远和它对应的内容匹配;回写-缓存不会立即把写操作传递到下一级,而是仅修改本级缓存中的数据,并且把对应的缓存数据标记为脏数据,脏数据会触发回写,也就是把里面的内容写到对应的内存或下一级缓存中,回写后,脏数据又变干净了,当一个脏数据被丢弃的时候,总是想要进行一次回写。

缓存一致性问题

例:i++;
当线程运行这段代码时

  • 1.首先会从主内存中读取i;
  • 2.然后复制一份到CPU高速缓存中,然后CPU执行+1操作;
  • 3.然后数据+1后的结果写入到高速缓存中;
  • 4.最后将结果刷新到主内存中。
    在多线程中,会有问题。
    加入两个线程AB都在执行i++;
    正常逻辑主内存的值应该是3
  • 1.A,B两个线程从主内存中读取i的值到各自的告诉缓存中;
  • 2.然后线程A执行+1操作并将结果写入高速缓存中,最后写入主内存;
  • 3.此时主内存i==2,线程B做同样的操作,主内存中i的值被更新成2;
  • 4.所以AB执行完以后,最终结果是2不是3
    以上就是缓存一致性问题

缓存一致性协议

解决缓存一致性方案有两种:

  • 1.通过在总线加LOCK#锁的方式
  • 2.通过缓存一致性协议
    方案1存在一个问题,它是采用一种独占的方式实现的,相当于单线程,效率低
    在多核CPU系统中,每个CPU核心都有自己的一级缓存,二级缓存等,这样一来当多个核心在对共享的数据进行操作时,就需要保证该共享数据在所有CPU核心中的可见性/一致性。

窥探技术

【窥探技术+MESI协议】的出现,就是为了解决多核CPU时代,缓存不一致问题的。
“窥探”背后的思想是,所有内存传输都发生在一条共享的总线上,所有的CPU都能看到这条总线。
缓存本身是独立的,但是内存是共享资源,所有的内存访问都要经过仲裁(arbitrate):同一个指令周期中,只有一个缓存可以读写内存。
窥探技术的思想是,缓存不仅仅在做内存传输时才和总线打交道,而是不停地在窥探总线上发生的数据交换,跟踪其他缓存在做什么。
所以当一个缓存代表它所属的CPU去读写内存时,其他CPU都会得到通知,它们由此以来使自己的缓存保持同步。只要某个CPU一写内存,其他CPU马上就知道这块内存在它们自己的缓存中对应的缓存行已经失效。

MESI协议

缓存系统操作的最小单位是缓存行,而MESI是缓存行四种状态的首字母缩写,任何多核系统中的缓存行都处于这四种状态之一。

  • 1.失效(invalid)缓存行:该CPU缓存中无该缓存行,或缓存中的缓存行已经失效了。
  • 2.共享(shared)缓存行:缓存行的内容是同主内存内容保持一致的一份拷贝,这种状态下的缓存行只能被读取,不能被写入。多组缓存可以同时拥有针对同一内存地址的共享缓存行。
  • 3.独占(exclusive)缓存行:和S状态一样,也是和组内存内容保持一致的一份拷贝,区别在于,如果一个CPU持有了E状态的缓存行,那其他CPU就不能持有该内容的缓存行,这意味着,如果其他CPU原本也持有同一缓存行,那么他会马上变成失效状态。
  • 4.已修改(modified)缓存行:该缓存行已被所属CPU修改,其他CPU缓存中的拷贝马上变成失效状态,此外,已修改缓存行如果被丢弃或标记失效(M–>I),那么先要把它的内容回写到内存中,这和回写模式下常规处理方式一样。

总结

  • 只有但缓存行处于E和M状态时,CPU才能去写。这两种状态下CPU是独占缓存行的
  • 当CPU想写某个缓存时,如果它没有独占权,它必须先发送一条请求给总线,这会通知其他CPU把它们拥有的同一缓存行的拷贝失效
  • 只有在获取独占权后,CPU才能开始修改数据,并且此时CPU知道这个缓存行只有一份拷贝,在我自己的缓存里,所以不会冲突。
  • 反之,如果有其他CPU想读取这个缓存行(我们马上就能知道,因为我们一直在窥探总线),独占或者已修改的缓存行必须先回到共享状态。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值