我需要用锁来保护这个变量吗?

Sco*_*ott 8 c++ synchronization

所以我在多处理器机器上有一个C++的布尔类型.变量开始生命为真,然后有几个线程,其中任何一个或多个可能将其写为假.

同时,这些线程也可以读取此变量以检查其状态.我不关心如果读取此变量与任何写入同步,它们每个都发生在代码中的不同位置,并且无论是在任何特定写入之前还是之后都无关紧要.现在,我需要一个锁定这个布尔值?

我需要锁定的唯一方法是,如果处于非常低的水平,内存可能会被两次竞争写入损坏.例如,如果处理器A上的汇编指令在处理器B执行相同操作的同时将0写入表示布尔值的字节...而不是写入0,则内存最终为值22或一些东西.这可能搞砸了.

所以,一般来说,如果proc A正在写3到一个内存位置,而proc B写7,没有同步,我保证最终得到3或7?还是容易打破记忆?

编辑:

谢谢你的评论.更多信息:当然程序中有同步.总而言之,有问题的标志是告知某个内存池是否"脏"(需要压缩).因此,任何线程都可以决定将此标志设置为false(意味着池是脏的).例如,从池中释放内存会使其变脏.然后,任何线程都可以读取此标志并设置另一个标志以指示需要清理 - 当从池中分配内存时执行此检查,如果内存不足则会发出清除信号.在迭代之间的主要关键部分的某处,每个线程都要查找更多要处理的数据,我将让线程检查第二个标志,并做一些适当的事情来确保:所有其他的theads完成当前的迭代,一个线程清理记忆,

所以我认为我不需要锁定,因为:锁定会确保写入不会与另一次写入或读取同时发生.但谁在乎呢,只要硬件没有让我失望,最糟糕的情况是读取在写入之前或之后随机发生 - 如果我用锁保护它会发生同样的事情,就在那时我们真的确定它是在......之前或之后...

我认为同样的论点适用于我上面提到的第二个标志.

Nik*_*sov 10

在大多数商品硬件上,单个字读/写是原子的,因此,对同一存储器位置的两次(或多次)竞争写入(和读取)不会破坏该值.这里重要的是CPU之间的缓存一致性.

同样,在商品硬件上你可能只是标记单个布尔变量volatile(已经被声明为并发编程btw无用)以防止编译器将其优化到寄存器中,但仅当你真的不关心命令时写作

让我用一个检查表重复这个:

  • 你准备好了吗会丢失一些布尔值的更新?
  • 你确定源代码中的布尔值翻转之前没有其他内存更新,但是翻转之后可能会重新排序吗?
  • 您确定不关心申请中的活动顺序吗?

如果你有三个强烈的"是"答案,那么你可能会因为没有保护那个标志而逃脱.仍然要考虑在读取变量之前插入获取内存屏障,并在写入之前释放内存屏障.我的建议是重新思考设计,并列出明确的同步线程间通信和事件排序.

希望这可以帮助.


Gor*_*aci 8

如果只检查变量的状态并在某个方向上将其设置为false,那么除了某些线程可能有点迟,看到变量已经设置为false之外,没什么可担心的.(这可以通过使用'volatile'关键字在某种程度上克服.)然后两个线程可以将其设置为false,这没有问题,因为变量在一个方向上设置为单个值.假设对内存位置的布尔写入不保证是原子的,有什么危害?他们都写的最终值是相同的.

不过,如果出现以下情况,您将不得不使用锁定方法:

  • 值设置不仅仅是单向:您将其设置为false,然后再设置为true,然后再设置为false等.
  • 您对线程将值设置为false的信息采取某些相关操作.因为显然可能有两个赢家.