仅在加入/减少变量时是否需要互斥锁?

时间:2016-06-01 13:05:12

标签: c synchronization pthreads mutex

我有一个带有一些整数字段的结构,比如

struct s {
    int a;
    int b;
    int c;
    int max;
};
struct s mystruct = {0, 0, 0, 0}; // Global var

然后我有N个线程,有时必须在前三个字段上执行++--之类的操作,有时必须读取它们然后更新max字段。我必须在这里使用互斥吗?如果是,是否只在阅读/更新max或始终?为什么?如果我只是增加或减少前三个字段,那么一个线程在另一个字段之前运行是否重要?

3 个答案:

答案 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