多线程环境中锁作用域不当造成其他线程无法及时接收通知的情况

今天在写线程池的时候遇到一个奇怪的情况,在网上也没找到答案,特此记录。

简要描述:在子线程改变了某个值而通知其他线程执行时,其他线程应该会结束在条件变量处的等待,立马进行相应操作,但是遇到了其他线程一直卡住而没有执行得到相应输出的问题。

后面经过 debug 发现是因为在涉及锁和条件变量的代码在一起时,没有明确锁的作用域,造成该锁作用的变量经过修改后,本来是要通知其他线程使用这个修改后的变量的,但是因为锁作用域不当导致其他线程没有及时收到这个变量改变的通知。

接下来写一个最小验证代码说明情况:

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

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print1() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] {
        return ready;
    });
    std::cout << "1" << std::endl;
}

void print2() {
    // 问题所在
    std::unique_lock<std::mutex> lock(mtx);
    ready = true; 
    
    std::cout<< 2 <<std::endl;
    
    cv.notify_all(); 
    
    // 更多耗时操作
}

int main() {
    std::thread t1(print1);
    std::thread t2(print2);

    t1.join();
    t2.join();

    return 0;
}

在这里注意 print2() 函数,我加锁修改 ready 后,通知其他线程,这时候 print1() 函数应该会接收到通知从而打印 “1”,但是此时终端只打印 2,没有打印 1。原因在于此时 print2 函数中的锁作用于整个 print2 函数,只有当 print2 函数执行完,条件变量的通知才会到 print1 函数那里,造成了print1 函数严重延迟。

当按如下方式在 print2 函数中的锁周围加上作用域后,print1 函数立马执行打印了 1,也就是说 print2 函数发送的通知马上到了 print1 所在线程。

void print2() {
    {
        std::unique_lock<std::mutex> lock(mtx);
        ready = true; 
    }
    std::cout<< 2 <<std::endl;
    
    cv.notify_all(); 
    
    // 更多耗时操作
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值