繁体   English   中英

如何使C ++中的对象易失?

[英]How to make an object in c++ volatile?

`struct MyClass {
  ~MyClass() {
    // Asynchronously invoke deletion (erase) of entries from my_map;
    // Different entries are deleted in different threads.
    // Need to spin as 'this' object is shared among threads and 
    // destruction of the object will result in seg faults.
    while(my_map.size() > 0); // This spins for ever due to complier optimization.
  }
  unordered_map<key, value> my_map;
};`

我有上面的类,其中无序映射的元素在析构函数中被异步删除,并且我必须旋转/睡眠,因为该对象在其他线程之间共享。 我无法将my_map声明为volatile因为它会导致编译错误。 我还能在这里做什么? 我如何告诉编译器my_map.size()在某个时间点将为0。 请不要告诉我为什么/这种设计不好。 由于无法解释的原因,我无法更改设计,除非我在此处编写了数千行代码。

编辑:使用自旋锁的版本保护my_map 因此,线程在擦除条目之前确实会抓住自旋锁。 只是while(my_map.size() > 0); 是我在代码中唯一的“天真”旋转。 我将其转换为抓取自旋锁,然后(循环查看)大小并正常工作。 尽管使用condition_variable是正确的方法,但我们使用异步编程模型(例如SEDA),该模型将我们绑定为使用任何休眠/后退调用。

volatile不是解决此问题的方法。 volatile具有三种用途:1.访问驱动程序中的内存映射设备; 2.信号处理程序; 3. setjmp用法。

阅读下面的,一遍又一遍,直到它下沉。 volatile是在多线程没用。

像这样的天真自旋锁有三个问题:

  1. 允许编译器缓存结果,因此您将看到“永远旋转”的行为。
  2. 在经典情况下,您有竞争条件的风险:线程A可能会检查锁变量,发现资源可访问,但是在设置锁变量之前先被抢占。 随之而来的是线程B ,该线程B也找到了显示资源可访问的锁变量,因此它对其进行锁定并开始访问该资源,然后线程A唤醒并再次锁定该变量,并访问该资源。
  3. 存在数据写入顺序问题。 如果写入一个受保护的变量,然后更改了一个锁变量,则您无法保证其他线程也不会看到该受保护的变量,即使它也可能看到声称已被写入的锁变量。 允许编译器 CPU上的乱序执行。

volatile仅解决了第一个问题,对解决另外两个问题无济于事。 需要注意的是,即使标准不要求,默认情况下,x86 / x64上的MSVC也会在volatile访问中添加内存屏障。 碰巧解决了第三个问题,但仍然不能解决第二个问题。

解决所有这三个问题的唯一方法是使用正确的同步原语: std::atomic<>如果您确实必须旋转锁),最好是std::mutex ,也许还需要std::condition_variable来获得使线程进入睡眠std::condition_variable的锁直到发生一些有趣的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM