前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何理解互斥锁

如何理解互斥锁

作者头像
无敌清风蓝
发布2024-06-04 19:51:57
680
发布2024-06-04 19:51:57
举报
文章被收录于专栏:无敌清风蓝无敌清风蓝

互斥锁

使用条件变量的 wait 函数来等待特定条件

代码语言:javascript
复制
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>

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

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; }); // 等待 ready 变量为真
    std::cout << "Worker thread is running" << std::endl;
}

int main() {
    std::thread t(worker);

    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true; // 设置 ready 变量为真
    }
    cv.notify_one(); // 唤醒等待的线程

    t.join();

    return 0;
}

这个例子中定义了一个互斥锁 mtx,一个条件变量 cv 和一个布尔变量 readyworker 函数是一个线程函数,它在一个独立的线程中运行。

worker 函数中,首先创建了一个 std::unique_lock 对象 lock,用来锁定互斥锁。然后调用条件变量的 wait 函数等待特定条件。wait 函数接受两个参数:一个互斥锁和一个谓词函数。谓词函数用来检查特定条件是否满足。在这个例子中,谓词函数是一个 lambda 表达式,它返回 ready 变量的值。

当调用 wait 函数时,它会自动解锁互斥锁并阻塞当前线程,直到条件变量被唤醒。当条件变量被唤醒时,wait 函数会自动锁定互斥锁,并调用谓词函数检查特定条件是否满足。如果谓词函数返回 true,则表示特定条件已经满足,此时 wait 函数会返回。否则,wait 函数会继续阻塞当前线程,直到条件变量再次被唤醒。

在主函数中,首先创建了一个线程 t,并将其与 worker 函数关联。然后使用花括号创建了一个临时作用域,在该作用域中创建了一个 std::lock_guard 对象 lock,用来锁定互斥锁。接着将 ready 变量设置为 true,表示特定条件已经满足。最后调用条件变量的 notify_one 函数唤醒等待的线程。

需要注意的是,在访问共享变量(如 ready 变量)时,需要使用互斥锁来保护对它的访问。在这个例子中,使用了 std::lock_guard 类来管理互斥锁。当创建一个 std::lock_guard 对象时,它会自动锁定互斥锁;当 std::lock_guard 对象销毁时,它会自动解锁互斥锁。

条件变量的工作原理

可以将条件变量比作一个闹钟,它可以让线程进入睡眠状态,并在特定条件下唤醒线程。当调用条件变量的 wait 函数时,线程就像是一个人躺在床上,按下了闹钟的按钮,然后进入了睡眠状态。此时,线程不会执行任何操作,直到被唤醒。

当其他线程调用条件变量的 notify_onenotify_all 函数时,就相当于闹钟响了。此时,等待的线程会被唤醒,就像人被闹钟吵醒一样。当线程被唤醒后,它会检查特定条件是否满足。如果特定条件已经满足,则线程会继续执行;否则,线程会再次进入睡眠状态,继续等待被唤醒。

例如,在上面的例子中,特定条件是 ready 变量为真。当调用 wait 函数时,线程会进入睡眠状态,并等待 ready 变量变为真。当主函数中将 ready 变量设置为真并调用 notify_one 函数时,等待的线程就会被唤醒。此时,它会检查 ready 变量是否为真。由于 ready 变量已经被设置为真,因此特定条件已经满足,此时 wait 函数会返回。

wait自动解锁互斥锁并阻塞当前线程

可以将互斥锁比作一扇门,它可以防止多个线程同时访问共享资源。当一个线程需要访问共享资源时,它需要先锁定互斥锁,就像用钥匙把门锁上一样。当线程访问完共享资源后,它需要解锁互斥锁,就像用钥匙把门打开一样。

而条件变量可以比作一个闹钟,它可以让线程进入睡眠状态,并在特定条件下唤醒线程。当调用条件变量的 wait 函数时,线程就像是一个人躺在床上,按下了闹钟的按钮,然后进入了睡眠状态。此时,线程不会执行任何操作,直到被唤醒。

当调用 wait 函数时,它会自动解锁互斥锁并阻塞当前线程。这就像一个人躺在床上,按下了闹钟的按钮,然后起身去开门,把门打开,再回到床上继续睡觉。此时,其他线程就可以进入房间(锁定互斥锁)并访问共享资源。

当其他线程调用条件变量的 notify_onenotify_all 函数时,就相当于闹钟响了。此时,等待的线程会被唤醒,就像人被闹钟吵醒一样。当线程被唤醒后,它会起身去关门(锁定互斥锁),然后检查特定条件是否满足。如果特定条件已经满足,则线程会继续执行;否则,线程会再次进入睡眠状态,继续等待被唤醒。

共享资源是房间里的一个东西吗

是的,在这个比喻中,共享资源可以比作房间里的一个东西,例如一张桌子或一个柜子。多个线程可以比作多个人,它们都想进入房间并使用这个共享资源。

由于共享资源只能被一个线程(人)同时访问,因此需要使用互斥锁(门)来防止多个线程(人)同时访问共享资源。当一个线程(人)需要访问共享资源时,它需要先锁定互斥锁(关上门),然后才能访问共享资源。当线程(人)访问完共享资源后,它需要解锁互斥锁(打开门),以便其他线程(人)可以进入房间并访问共享资源。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023/06/15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 互斥锁
  • 条件变量的工作原理
  • wait自动解锁互斥锁并阻塞当前线程
  • 共享资源是房间里的一个东西吗
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档