【问题标题】:Is semaphore needed for read/write access to a boolean对布尔值进行读/写访问是否需要信号量
【发布时间】:2016-03-03 15:33:33
【问题描述】:

我了解保护复杂数据结构的必要性。像链表一样,带有信号量。我已经看到当一个线程修改列表而另一个线程正在遍历列表时可能发生的坏事。

但是对于一个非常简单的数据字段(例如布尔值)是否需要这样做?在我工作的地方,我会看到很多类似下面示例的代码,或者代码审阅者要求我添加这些代码。这真的需要吗?如果是这样,有人可以解释如果不使用信号量会出现什么问题吗?

#define TRUE  1
#define FALSE 0
static int enabled;

int is_foo_enabled(void)
    {
    int ret;
    reserve_foo_semaphore();
    ret = enabled;
    release_foo_semaphore();
    return ret;
    }

void enable_foo(void)
    {
    reserve_foo_semaphore();
    enabled = TRUE;
    release_foo_semaphore();
    }

void disable_foo(void)
    {
    reserve_foo_semaphore();
    enabled = FALSE;
    release_foo_semaphore();
    }

【问题讨论】:

  • int 不是布尔类型。您可以使用stdatomics.h 作为轻量级替代方案。
  • 视情况而定......

标签: c multithreading semaphore


【解决方案1】:

原子访问保证多件事(取决于内存模型语义) -

  • 对于较大的数据大小(甚至是 POD),它保证读取或写入是原子完成的,即使值被拆分到不同的缓存行甚至页面。
  • 对于 Read-Modify-Write 类型的操作,它保证读取和写入是原子完成的,因此没有线程可以读取过时的数据,而另一个线程正在修改值的过程中。另一种看待这一点的方式是,原子访问保证 CPU 将在读写操作之前或之后对所有其他读/写进行排序,而不是在它们之间。
  • 根据您的内存模型(防护、序列化等),可能会适用额外的保证。

关于第一个项目符号不适用于布尔类型是正确的(尽管这取决于您的系统,谁知道布尔是如何在那里实现的......),但其他保证仍然很重要。

【讨论】:

    【解决方案2】:

    是的,它是必需的,例如你的一个线程可以检查这个值,并依赖它是false,然后它开始做类似false 的事情,但在此之前,其他一些线程将其更改为是真实的,并且不再需要采取行动,甚至可能导致错误。此外,即使更改布尔值也不是真正的原子操作,或者至少可能不是原子操作,因此当线程(或进程,例如,如果我们谈论共享内存)将同时改变这个值。因此,当您的代码尝试检查或更改任何共享值,甚至是布尔值时,基本上您需要锁定和释放互斥锁。同样在您的问题的上下文中,即使它用作布尔值,您也只有一个 int,我认为没有人认为他不需要用于更改整数的 mutext。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      • 1970-01-01
      • 2016-01-07
      相关资源
      最近更新 更多