C++ 仅与Win32事件同步的std::vector更改的跨线程可见性

C++ 仅与Win32事件同步的std::vector更改的跨线程可见性,c++,windows,multithreading,concurrency,memory-model,C++,Windows,Multithreading,Concurrency,Memory Model,假设我有一个std::vector类成员变量,其中Item是具有getter和setter的某个类。 它是在一个线程1中创建的,但从另一个线程2用push_back填充。最后,它在线程1中读取。对它的访问仅与Windows同步。当向量被填满时,事件被设置为信号状态 在这种情况下,我是否应该提防跨线程可见性问题—获取过时的值?如果是,如何防止这些问题?我建议尽可能使用标准同步原语 您需要锁定一次,直到向量被填充。例如,thread2将等待thread1完成 using Item = int; st

假设我有一个std::vector类成员变量,其中Item是具有getter和setter的某个类。 它是在一个线程1中创建的,但从另一个线程2用push_back填充。最后,它在线程1中读取。对它的访问仅与Windows同步。当向量被填满时,事件被设置为信号状态


在这种情况下,我是否应该提防跨线程可见性问题—获取过时的值?如果是,如何防止这些问题?

我建议尽可能使用标准同步原语

您需要锁定一次,直到向量被填充。例如,thread2将等待thread1完成

using Item = int;
std::vector<Item> items;
std::mutex mutex;

// #1
auto t1 = std::thread([&items, &mutex](){
  std::lock_guard<std::mutex> lock(mutex);
  // fill in items...
  // ...
});

// #2
auto t2 = std::thread([&items, &mutex](){
  std::lock_guard<std::mutex> lock(mutex);
  // read...
});

// wait...
t1.join();
t2.join();

如果线程1只在2个信号后读取,而2在发出信号后不写入任何新成员,那么您就没有什么可担心的了


否则,如果读取和写入可能同时发生,则不会出现可见性问题,但会出现同步问题。vector不是线程安全的数据结构,因此如果两个线程同时访问它,它可能会损坏。要么切换到另一个线程安全的数据结构,要么用独占锁围绕向量访问。对于标准解决方案,请查看std::mutex。

微软表示,等待事件对象就足够了

根据:

以下同步功能使用适当的屏障来确保内存顺序:

进入或离开关键部分的函数 向同步对象发送信号的函数 等待功能 互锁功能
这意味着,如果线程1看到发出信号的事件对象的副作用,它必须看到线程2修改向量的副作用。

1将如何操作数组?永远填充向量一次?还是会在第二次添加项目?如果是这种情况,您还需要锁,那么事件是不够的。@AndreaRossini 1只创建向量,然后运行2,在它完成后,即事件被通知后,只读取结果。如果我理解正确,线程2停止访问向量或在事件被通知后完全停止执行,您不需要进一步的同步。也许您可以创建一个。不清楚为什么这是线程化的,因为您正在以序列化的方式做两件事。如果我不使用你的事件,但可以访问你的二进制文件,我想我会把事情搞砸的。Windows中还有许多其他同步对象:。关键部分通常用于同步对成员国的访问。您不能保证t2不会在t1之前获得互斥锁。