信号量是否需要对布尔值进行读/写访问

时间:2016-03-03 15:33:33

标签: c multithreading semaphore

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

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

#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();
    }

2 个答案:

答案 0 :(得分:1)

原子访问保证了多种功能(取决于内存模型语义) -

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

你对第一个不适用于布尔类型的子弹是正确的(虽然这取决于你的系统,谁知道如何在那里实现布尔值......),但其他保证仍然很重要。

答案 1 :(得分:0)

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