编写多线程应用程序时,遇到的最常见问题之一是竞争条件.
我对社区的问题是:
什么是比赛条件?你怎么发现它们?你怎么处理它们?最后,你如何防止它们发生?
我正在编写一个程序,用于计算国际象棋变体的终结表基础.填充tablebase的算法如下:
unsigned char
,每个成员代表一个位置(我们总是假设它是白色的).即使位置丢失也是数组成员,如果赢了则是奇数,如果它是0xff
无效的,0xfe
如果它是平局的话.0xff
,白色与其匹配的每个位置0x00
以及所有其他位置0x0fe
.0xfe
.检查是否存在是导致其数组成员为偶数的位置,如果有,写一加那个位置为对应于CURREN位置上的成员数量的举动.如果所有的移动导致由奇数显示位置(即这是一个失去位置),纪念这个位置一加最高这些数字来表示防御最强的花费多长时间.为了速度,我想并行化第三步.仔细阅读会产生在每次迭代中,我们只会将一个值(迭代次数)写入数组.以下策略获得:
0xfe
,因为这意味着该成员刚刚被另一个线程同时写入.现在显然这个程序中存在竞争条件,但是没关系,因为如果没有任何粉红色的大象(如果a char
是原子写的则不能存在),我们总能得到正确的结果.但是,由于在纸面上存在竞争条件,C编译器可能会声明我的程序未定义并格式化我的硬盘.
如何在不违反C内存模型的任何约束的情况下并行化此算法并且不会导致大量减速(例如通过添加锁定),我该怎么做?
这是一个简化的算法,它演示了相同的概念,但剥离了所有不重要的东西:
unsigned char a[n]
.每个数组成员都是0或1.由于我们只将0更改为2,因此我们处理数组条目的顺序并不重要,即使我们并行执行竞争条件(因为我们同时读取/写入相同的对象) .如何在不牺牲性能的情况下告诉编译器它不应该关心竞争条件?