我试图实现Peterson算法。在我的main
中,我得到的时间不再是结果20000。
你能解释一下这种行为吗?我不太确定我是否正确实现了算法。
问候
// Implementing Peterson Algorithm
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
volatile int turn = 0;
volatile int flag[2] = { 0 };
int num = 0;
pthread_t thread[2];
void *count0(void *t) {
flag[0] = 1;
turn = 1;
while (flag[1] == 1 && turn == 1) continue;
for (int i = 0; i < 10000; i++) {
num++; // critical section
}
flag[0] = 0;
}
void *count1(void *t) {
flag[1] = 1;
turn = 0;
while (flag[0] == 1 && turn == 0) continue;
for (int i = 0; i < 10000; i++) {
num++;
}
flag[1] = 0;
}
int main() {
while (1) {
pthread_create(&thread[0], NULL, count0, NULL);
pthread_create(&thread[1], NULL, count1, NULL);
pthread_join(thread[0], NULL);
pthread_join(thread[1], NULL);
printf("num = %d\n", num);
if (num != 20000) { printf("!!!!!!"); exit(0); }
num = 0;
}
return 0;
}
答案 0 :(得分:1)
Petersen算法是在1981年设计的,它适用于简单的处理器,但它不再适用于可能重新排序内存访问的现代CPU,除非采取特定的预防措施来确保访问顺序,这需要非标准语言扩展。
引用维基百科文章:https://en.wikipedia.org/wiki/Peterson%27s_algorithm
请注意
在硬件级别工作时,通常不需要Peterson的算法来实现原子访问。某些处理器具有特殊指令,如测试和设置或比较和交换,通过锁定内存总线,可用于在SMP系统中提供互斥。
大多数现代CPU重新排序内存访问以提高执行效率(请参阅允许的重新排序类型的内存排序)。这样的处理器总是提供某种方式来强制在存储器访问流中进行排序,通常是通过存储器屏障指令。在对存储器访问重新排序的处理器上实现Peterson和相关算法通常需要使用这些操作来正确地工作以使顺序操作不以错误的顺序发生。请注意,即使在不重新排序指令的处理器(例如Xbox 360中的PowerPC处理器)上也可能发生内存访问的重新排序。
大多数此类CPU也具有某种保证的原子操作,例如x86处理器上的XCHG和Alpha,MIPS,PowerPC和其他体系结构上的加载链接/存储条件。这些指令旨在提供一种比纯共享内存方法更有效地构建同步原语的方法。