-
内存缓存
-
缓存数据
- 每个线程使用处理器进行计算的时候,都会将一些需要的数据放入缓存.
-
适用场景
- 每个线程只操作自己的数据,即线程内的局部变量是没有问题的。
- 但是如果是操作全局变量,这种共享数据,就造成了两个核心的高速缓存在两个处理器缓存中都有一份,修改就需要保证一致性问题。
-
多线程修改全局变量数据结果错误
- 因为多线程之间的缓存不一致。
-
处理器提供的缓存一致
-
一致性
-
早期
- 某个处理器修改数据,发送
invalidate
给其他处理器,其他处理器收到将对应数据缓存清空,然后发送响应信息invalidate ack
. - 发送处理器接收到响应之后,再进行修改。
- 其他处理器需要适用就需要再次读,从其他处理器或内存中读数据.
- 缺点:阻塞应答效率不高.
- 某个处理器修改数据,发送
-
改进
- 发送处理器添加了一种缓存机制
store buffer
,将要修改的数据放进去,继续执行,等到接收完了invalidate ack
再进行修改。 - 这样的操作就提高了效率。但是我方使用的时候就造成了,读取缓存的数据,也是旧数据。
- 发送处理器添加了一种缓存机制
-
再改进
- 我方读取数据的时候先从
store buffer
中读,再从缓存中读。 - 新问题:再等待
invalidate ack
的过程,可能会有很多的要修改的数据,store buffer
存不下,还是要停下来等待。
- 我方读取数据的时候先从
-
再再改进
- 处理器提供了
invalid queue
,接收到了就立刻返回invalidate ack
,然后表示我方已经收到,随后处理. - 这时候,就有了应答非常快,但是数据仍然不正确.
(效率高就很可以了,因为大部分都是使用的局部变量,不会使用共享的全局变量)
- 那么处理器全局变量怎么办呢。
- 处理器提供了
-
解决策略
- 使用锁,以此来独占数据,我方使用的时候,其他要使用的就睡眠,也就是不适用处理器。
- 但是造成的效果就是并发数不高.
- 然后就有了内存屏障,但是使用的方位呢就是读多,写少的情况.如果写多,效率也不好.这种并发高.
-
-
-
内存屏障
-
读内存屏障
-
写内存屏障
-
代码
a = 0 , b = 0; void fun1() { a = 1; smp_mb(); b = 1; } void fun2() { while (b == 0) continue; smp_rmb(); assert(a == 1); }
-
简单案例
#include<stdio.h> #include<pthread.h> static int funca = 1; int flag = 1; void * func1(void*) { for(int i = 0 ; i < 10000000 ; i++) { __asm__ __volatile__("mfence":::"memory"); funca += 1; } flag = 0; } void *func2(void*) { int temp = 0 ; while(flag) { __asm__ __volatile__("lfence":::"memory"); if(funca % 1000000 == 0) { printf("%d\n",temp++); } } } int main() { pthread_t t1,t2; pthread_create(&t2,NULL,func2,NULL); pthread_create(&t1,NULL,func1,NULL); pthread_join(t1,NULL); pthread_join(t2,NULL); }
-
内存屏障简单理解
最新推荐文章于 2024-12-26 18:32:36 发布