内存一致模型——顺序一致模型

2019-04-14 17:00发布

内存一致模型——顺序一致模型

顺序一致模型,是最常见的内存一致模型,定义如下:
【如果一个多处理器系统是顺序一致的】,那么,无论程序怎么运行,结果都与各处理器各自轮流运行后的结果相同,且各处理器内部的执行顺序由程序决定。
从定义中, 可以得出,顺序一致模型有如下要求: - 保证单一处理器内部的执行顺序 - 保证多处理器操作同一块内存时的先后顺序 如图所示: 顺序一致性图示 总线结构保证在相同时间内对指定内存块的访问只有一个处理器。这样就保证多处理器之间不会冲突。 下面展示引用文献[1]中的两个例子(a) (b): 这里写图片描述 (a)中就用到了Dekker算法,过程一目了然,放一段代码吧 #include size_t signal1 = 0; size_t signal2 = 0; volatile bool entered1 = false; volatile bool entered2 = false; DWORD __stdcall worker1Thread(LPVOID param) { for (int i = 1; i < 100000;) { //printf("a1 "); signal1 = 1; //printf("a2 "); size_t tsig = signal2; if (tsig == 0) { // printf("a3 "); entered1 = true; // printf("a4 "); // printf("id : %d ", 1); bool violated = entered2; if (violated) printf("worker1 violated"); // printf("a5 "); entered1 = false; // printf("a6 "); //printf("checked : ",) i++; } // printf("a7 "); signal1 = 0; // printf("a8 "); } return ERROR_SUCCESS; } DWORD __stdcall worker2Thread(LPVOID param) { for (int i = 1; i < 100000;) { // printf("b1 "); signal2 = 1; // printf("b2 "); size_t tsig = signal1; if (tsig == 0) { // printf("b3 "); entered2 = true; // printf("id : %d ", 2); // printf("b4 "); bool violated = entered1; if (entered1) printf("worker2 violated"); // printf("b5 "); entered2 = false; // printf("b6 "); i++; } // printf("b7 "); signal2 = 0; // printf("b8 "); } return ERROR_SUCCESS; } void test24() { CloseHandle(CreateThread(NULL, 0, worker1Thread, NULL, NULL, NULL)); CloseHandle(CreateThread(NULL, 0, worker2Thread, NULL, NULL, NULL)); } 为什么有这么多注释?因为如果你运行这段代码你会发现,会以极低的概率报violated。仔细想想,代码好像又没什么问题。 经过再仔细的分析之后发现,如果某线程在将signal置0之后被操作系统剥夺了cpu时间,那么就会导致冲突出现。下面就会分析无缓存及有缓存情形的一致性模型。

无缓存架构

在很多现如今的CPU实现中,都会有写入缓冲区来作为硬件加速的一种手段。也就是说,CPU对内存的操作会先保存在写入缓冲区中,继而写入内存,而这种行为就导致内存操作非原子。对于单处理器系统而言,并不存在这种问题,因为只有一个处理器,所以写入缓冲区也就只有一个。但是对于多处理器系统来说,就另当别论了,因为各个处理器用的并不是同一块定写入缓冲区,so,问题来了。

多核心多写入缓冲区情况

第一种情形,我们来看一下保证内存写入读取顺序的重要性。在Dekker算法中,对于一个顺序一致模型来说,当进行互斥区进入判断时,并不会存在两个信号量都为0的情况出现。在这种情形下就会出现这种冲突,如图所示: 多核心多写入缓冲区 单个核心在读取某内存时,会先检查自己写入缓冲区中是否包含对应地址的内存写入,如果存在则返回写入的值,如上文所提,单核心系统不会存在冲突问题;而如果不存在,则会直接到内存中读取数据。如果有多个核心,图中所示就是引起冲突的原因。 引用:
[1] Sarita V. Adve, Kourosh Gharachorloo.Shared Memory Consistency Models:A Tutorial[R].Palo Alto, California 94301 USA:WRL,1995.