我有一个带有一些整数字段的结构,比如
struct s {
int a;
int b;
int c;
int max;
};
struct s mystruct = {0, 0, 0, 0}; // Global var
然后我有N个线程,有时必须在前三个字段上执行++
或--
之类的操作,有时必须读取它们然后更新max
字段。我必须在这里使用互斥吗?如果是,是否只在阅读/更新max
或始终?为什么?如果我只是增加或减少前三个字段,那么一个线程在另一个字段之前运行是否重要?
答案 0 :(得分:9)
并发的通用规则是:如果以非原子方式同时访问内存位置,并且并非所有访问都是读取,则必须对访问进行排序。可以通过锁定互斥锁来序列化访问,或者通过某些较低级别的操作(如有序的原子访问或有序的栅栏)来进行排序。
如果所有访问都是读取,则唯一允许无序访问的时间。例如。多个线程可以读取(非原子)常量而无需排序。
答案 1 :(得分:4)
如果您执行的操作不是原子操作,则需要同步对变量的访问。
考虑具有初始值(例如5)的单个变量a
的场景。
现在我们有两个线程T1和T2,都希望增加它。如果增量操作不是原子的(例如,它可能是其他方式),如何分解增量操作?
1)将a
值读入临时位置
2)递增并将临时位置写回a
。
现在考虑一个场景T1首先执行此操作,然后仅在完成步骤1之后被T2抢占:
T1:1)将a
读入temp1
=> temp1=5
T2:1)将a
读入temp2
=> temp2=5
T2:2)将temp2+1
写入a
=> a=6
T1:2)将temp1+1
写入a
=> a=6
所以a
的最终价值将是6
,而不是7
,正如您所期望的那样。
答案 2 :(得分:0)
如果您有多个线程更新全局数据,那么您应该mutex
。
您应该在读取和写入两种情况下使用互斥锁。只读取常数数据没有问题。
如果您避免使用互斥锁,则无法获得所需的结果,因为其他线程无法获得正确的值。看看这个 When should we use mutex ?
请查看example。