从全球结构中读取时,我是否需要信号量?

JXG*_*JXG 9 c multithreading mutex semaphore global-variables

一个相当基本的问题,但我没有在任何地方看到它.

假设我们有一个全局结构(在C中),如下所示:

struct foo {
  int written_frequently1;
  int read_only;
  int written_frequently2;
};
Run Code Online (Sandbox Code Playgroud)

我似乎很清楚,如果我们有很多线程读写,我们需要written_frequently成员上的信号量(或其他锁),甚至是读取,因为我们不能100%确定这个结构的赋值是原子的.

如果我们想要很多线程来读取read_only成员,而没有人要写,那么我们需要一个关于struct access的信号量才能读取?

(我倾向于拒绝,因为不断更改前后位置的事实不会影响read_only成员,读取值的多个线程不应相互干扰.但我不确定. )


[编辑:我现在意识到我应该更好地问这个问题,以便非常明确地澄清我的意思.当然,当我第一次提出这个问题时,我并没有真正理解所涉及的所有问题.当然,如果我现在全面编辑这个问题,我将毁掉所有这些伟大的答案.我的意思更像是:

struct bar {
  char written_frequently1[LONGISH_LEN];
  char read_only[LONGISH_LEN];
  char written_frequently2[LONGISH_LEN];
};
Run Code Online (Sandbox Code Playgroud)

我问的主要问题是,由于这些数据是结构的一部分,它是否完全受其他结构成员的影响,并且可能会影响它们的回报?

在这种情况下,成员是整体的,因此写作可能是原子的,这实际上只是一个红色的鲱鱼.

Ada*_*iss 7

您需要一个互斥锁来保证操作是原子的.因此,在这种特殊情况下,您可能根本不需要互斥锁. 具体来说,如果每个线程写入一个元素并且写入是原子的并且新值独立于任何元素(包括其自身)的当前值,则没有问题.

示例:多个线程中的每个线程都更新一个"last_updated_by"变量,该变量只记录更新它的最后一个线程.显然,只要变量本身以原子方式更新,就不会发生错误.


但是,如果线程一次读取或写入多个元素,需要使用互斥锁来保证一致性,特别是因为您提到锁定元素而不是整个结构.

示例:线程更新结构的"日","月"和"年"元素.这必须以原子方式发生,以免另一个线程在"月"增量之后但在"日"包裹到1之前读取结构,以避免日期如2月31日.请注意,您必须在阅读时遵守互斥锁; 否则你可能会读到一个错误的半更新值.


Jon*_*son 6

如果read_only成员实际上是只读的,则不存在数据被更改的危险,因此不需要同步.这可以是在线程启动之前设置的数据.

无论频率如何,您都希望同步任何可写入的数据.


JXG*_*JXG 0

非常感谢所有出色的回答者(以及所有出色的答案)。

总结:

如果结构体中有一个只读成员(在我们的例子中,如果该值在任何线程可能想要读取它之前设置一次),则读取该成员的线程不需要锁、互斥体、信号量或任何其他成员。其他并发保护。

即使经常给其他成员写信也是如此。不同的变量都是同一结构的一部分这一事实没有什么区别。