C++ 如何在c++;不稳定的 `struct MyClass{ ~MyClass(){ //异步调用从my_映射中删除(擦除)条目; //在不同的线程中删除不同的条目。 //需要旋转,因为“this”对象在线程和 //物体的破坏将导致seg故障。 while(my_map.size()>0);//由于编译器的优化,这将永远旋转。 } 无序地图我的地图; };`

C++ 如何在c++;不稳定的 `struct MyClass{ ~MyClass(){ //异步调用从my_映射中删除(擦除)条目; //在不同的线程中删除不同的条目。 //需要旋转,因为“this”对象在线程和 //物体的破坏将导致seg故障。 while(my_map.size()>0);//由于编译器的优化,这将永远旋转。 } 无序地图我的地图; };`,c++,multithreading,asynchronous,volatile,unordered-map,C++,Multithreading,Asynchronous,Volatile,Unordered Map,在上面的类中,无序映射的元素在析构函数中异步删除,并且当对象在其他线程之间共享时,我必须旋转/休眠。我不能将my_map声明为volatile,因为它会导致编译错误。我还能在这里做什么?如何告诉编译器my_map.size()将在某个时间点产生0。请不要告诉我这个设计为什么/如何不好;我无法更改设计,因为它是绑定的,因为我无法解释原因,除非我在这里编写数千行代码 编辑:my_map使用spinlock版本进行保护。因此,线程在擦除条目之前会抓取自旋锁。只需while(my_map.size()>

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


编辑:
my_map
使用spinlock版本进行保护。因此,线程在擦除条目之前会抓取自旋锁。只需
while(my_map.size()>0)是我在代码中唯一“天真”的想法。我将它转换为抓取旋转锁,然后检查大小(在一个循环中),它成功了。虽然使用
条件变量是正确的方法,但我们使用异步编程模型(如SEDA),它使我们不使用任何休眠/休眠调用。

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

反复阅读以下内容,直到理解为止<代码>易失性
在多线程处理中是无用的

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

  • 编译器被允许缓存结果,因此您可以看到“永远旋转”的行为
  • 在典型情况下,您有竞争条件的风险:线程
    a
    可能会检查锁变量,发现资源是可访问的,但在设置锁变量之前会被抢占。线程
    B
    也找到显示资源可访问的锁变量,因此它将锁定并开始访问资源,然后thread
    A
    唤醒备份,再次锁定变量,并访问资源
  • 存在数据写入顺序问题。如果一个受保护的变量被写入,然后一个锁变量被更改,则不能保证另一个线程不会看到受保护的变量被更改,即使它也可能看到声明已写入的锁变量。编译器和CPU上的无序执行都允许这样做
  • volatile
    只解决了这些问题中的第一个,而没有解决其他两个问题。需要注意的是,默认情况下,x86/x64上的MSVC为
    volatile
    访问添加了内存限制,即使该标准不要求这样做。这恰好解决了第三个问题,但仍然无法解决第二个问题


    所有这三个问题的唯一解决方案是使用正确的同步原语:
    std::atomic
    ,如果您确实必须旋转锁,最好是
    std::mutex
    ,也可能是
    std::condition\u variable
    的锁,该锁将使线程进入睡眠状态,直到发生有趣的事情。

    考虑使用
    std::mutex
    来保护映射不受并发访问
    volatile
    会导致何种编译器错误?
    volatile
    不起作用你认为这几天它会做什么。大多数编译器都忽略了这个关键字,这并不能使任何东西更线程安全。您寻求的模式是,您需要一个std::condition_变量以及一个锁/互斥锁来保护对
    my_map
    的访问。但奇怪的是,
    my_map
    的拥有类如何在其他线程仍然引用其内部成员的情况下设法被破坏——这听起来像是一个设计问题。您是否考虑过对map实例使用std::shared_ptr?正如上面其他人所建议的,在我的地图访问权限周围需要一个互斥体。请告诉我。我只想添加一个指向的链接。
    volatile
    并不意味着原子!不能将其用于线程同步。使用
    std::atomic
    或锁。
    volatile
    在微基准测试中也很有用,因为它会抑制优化,因此可以用来防止编译器优化掉您想要度量的未使用的代码。但这是一个非常适合的用例。@JesperJuhl这实际上是我使用
    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;
    };`