在一个线程内进行的赋值在另一个线程中不可见

Assignment made inside a thread not visible in another thread

本文关键字:线程 另一个 赋值 一个      更新时间:2023-10-16

我正试图通过std::condition_variable和bool condition触发工作线程的执行。如果condition为true,则工作者等待通知并开始工作。在工作condition被设置为假之后。此外,还有一个互斥对象需要同步。

在主线程中,一个循环检查condition是否为false,如果是这种情况,则condition设置为true,并通知condition_variable。

当运行此代码时,我预计输出会"垃圾邮件"唤醒工作,但它只执行一次,因为thread_function()中对condition的分配在主线程中不可见/在工作线程中丢失。输出表明,在赋值之后它是false,当使用调试器进行调试时,它在赋值之后是false,但当评估主线程中的if时,它再次为true。

我是不是错过了什么?

我在VS2013和VS2012中尝试过这一点,并试图用std::atomic_bool替换bool,但这也没有帮助。

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include <atomic>
bool condition;
std::mutex condition_mutex;
std::condition_variable cv;
void thread_function() {
    while (true) {
        std::unique_lock<std::mutex> lock(condition_mutex);
        cv.wait(lock);
        std::cout << "woke upn";
        if (condition) {
            // do stuff
            std::cout << "thread workingn";
            condition = false;
            std::cout << "thread: " << (condition ? "true" : "false") << "n";
        }
    }
}
int main() {
    condition = false;
    std::thread t(&thread_function);
    while (true) {
        std::unique_lock<std::mutex> lock(condition_mutex);
//        std::cout << "main: " << (condition ? "true" : "false") << "n";
        if (!condition) {
            condition = true;
            cv.notify_one();
        }
    }    
    return 0;
}

您应该将锁放在while循环之外:

void thread_function() {
    std::unique_lock<std::mutex> lock(condition_mutex);
    while (true) {
        cv.wait(lock);
        std::cout << "woke upn";
        if (condition) {
            // do stuff
            std::cout << "thread workingn";
            condition = false;
            std::cout << "thread: " << (condition ? "true" : "false") << "n";
        }
    }
}

线程函数在重新进入循环时很快就会失去锁。这允许主线程在没有人等待的情况下调用cv.notify_one()

标准的等待方式包括测试条件,这将解决您的问题:

while (!condition) cv.wait(lock);

请参阅http://en.cppreference.com/w/cpp/thread/condition_variable/wait.