如何通知尾部更新到 C++ 窗口中的线程? [读取全局变量的未缓存值]

Posted

技术标签:

【中文标题】如何通知尾部更新到 C++ 窗口中的线程? [读取全局变量的未缓存值]【英文标题】:How to Notify Tail updates to threads in c++ windows? [Read uncached value for globals] 【发布时间】:2019-08-14 05:19:23 【问题描述】:

简介: 在下面的代码中,主函数创建 8 个线程,生产者一次填充一个有效负载数组,等待特定消费者读取它,然后移动到下一个索引。等待机制是,等待全局值被消费者清除。

//Producer
volatile int Payload[8];//global
CreateThread(); // 8 threads.
while(1)

    for(int i = 0; i < 8;i++)
     
        Payload[i] = 10;
        while(Payload[i]==10); //this is done to wait till thread reads and clears it.
    


//Consumer
while(1)

    if(Payload[threadindex])
    
        x = Payload[threadindex];
        Payload[threadindex] = 0;
        cout << "print" << endl;
    

这不起作用。不知怎的,我被困在了

while(Payload[i]==0);

我认为问题如下。

即使我将 Payload 保持为 volatile,程序仍会从缓存中读取它,因此会获取陈旧的值。

如何强制线程取消缓存值?

我一般如何解决这个问题?我对多线程比较陌生。

更新: 我看到 *** 建议使用以下链接。

Does guarding a variable with a pthread mutex guarantee it's also not cached?

其中提到了 pthread 函数执行内存屏障以确保缓存效果对其他线程可见。

我们在 Windows 上有什么东西吗?

【问题讨论】:

你应该发布一些真实的代码,这个伪代码并不能说明整个故事。例如,我不知道 "while (Payload[i]==0); 应该告诉我什么。 更新了我的帖子。 代码不是 C,而是 C++。 更新了标签。 易失性整数是“未缓存的”。你仍然可以有竞争条件。但这不是minimal reproducible example,并且 volatile int 标志不是通知线程的正确方法。 【参考方案1】:

实现生产者/消费者模型的常规方法是使用std::mutexstd::condition_variable

#include <mutex>
#include <thread>
#include <iostream>
#include <condition_variable>

int main()

    const size_t threadCount = 8;
    int payload[threadCount];
    std::condition_variable condition;
    std::mutex mutex;
    std::vector<std::thread> threads;
    for (size_t i = 0; i < threadCount; i++)
    
        threads.emplace_back([&, i]
        
            while (true)
            
                std::unique_lock lock(mutex);
                // wait until payload is non-zero
                condition.wait(lock, [&]  return payload[i] != 0; );
                int value = payload[i];
                payload[i] = 0;
                // tell the producer we have cleared the value
                condition.notify_all();
                // unlock mutex whilst we do our work to allow other threads/producer to keep running
                lock.unlock();
                std::cout << value << "\n";
            
        );
    
    while (true)
    
        for (size_t i = 0; i < threadCount; i++)
        
            std::unique_lock lock(mutex);
            // wait until payload is zero
            condition.wait(lock, [&]  return payload[i] == 0; );
            payload[i] = i;
            // tell the consumers we have set the value
            condition.notify_all();
        
    

这可以正确同步线程之间的数据,并且没有工作的线程处于空闲状态,而不是使用 100% CPU 连续检查某些工作的值。

注意负载数组不需要是易失性的。

【讨论】:

以上是关于如何通知尾部更新到 C++ 窗口中的线程? [读取全局变量的未缓存值]的主要内容,如果未能解决你的问题,请参考以下文章

从 WTL 和 C++ 中的工作线程更新 CListViewCtrl

C ++从异步线程更新Windows窗口

第三十四篇:在SOUI中使用异步通知

mfc c++ 从编辑控件更新文本文件

是否可以使用标准 C++ 线程而不是 FLTK 超时来更新窗口?

QT中UI主窗口如何与子线程相互传递参数