linux C++互斥锁std::lock_guard(轻锁)std::unique_lock(重锁)区别

Posted Dontla

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux C++互斥锁std::lock_guard(轻锁)std::unique_lock(重锁)区别相关的知识,希望对你有一定的参考价值。

文章目录

lock_guard和unique_lock区别

lock_guard 和 unique_lock 都是 C++ 标准库提供的互斥锁 RAII 封装工具,用于实现互斥访问,但它们有一些不同之处:

lock_guard 是基于互斥锁 std::mutex 实现的,unique_lock 是基于通用锁 std::unique_lock 实现的,unique_lock 可以实现比 lock_guard 更灵活的锁操作。
lock_guard 是不可移动的(moveable),即不能拷贝、赋值、移动,只能通过构造函数初始化和析构函数销毁,unique_lock 是可移动的,可以拷贝、赋值、移动。
unique_lock 提供了更多的控制锁的行为,比如锁超时、不锁定、条件变量等。
unique_lock 比 lock_guard 更重,因为它有更多的功能,更多的开销。如果只需要简单的互斥保护,使用 lock_guard 更好。

下面是 lock_guard 和 unique_lock 的简单使用示例,可以看出二者在使用方法上的区别

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

std::mutex m;

void worker()

    std::lock_guard<std::mutex> lg(m);  // lock_guard 方式上锁
    std::cout << "worker thread is running..." << std::endl;
    // 这里可以写一些需要互斥保护的代码
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "worker thread is done." << std::endl;
  // lock_guard 会在此自动释放锁

void another_worker()

    std::unique_lock<std::mutex> ul(m);  // unique_lock 方式上锁
    std::cout << "another worker thread is running..." << std::endl;
    // 这里可以写一些需要互斥保护的代码
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "another worker thread is done." << std::endl;
    ul.unlock();  // 手动释放锁
    //do something...
  // unique_lock 会在此自动释放锁

int main()

    std::thread t1(worker);
    std::thread t2(another_worker);
    t1.join();
    t2.join();
    return 0;

编译运行结果:

g++ test.cpp -lpthread && ./a.out 

示例:用std::lock_guard加互斥锁

std::lock_guard 是 C++11 中的标准库,是一个实现互斥锁的简单模板类。
它的使用方法很简单,只需要在代码中创建一个 std::lock_guard 对象,并传入一个互斥锁,在它的生命周期内,互斥锁的访问权限将被控制。

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <vector>

std::mutex mtx;
std::vector<int> data;

void func1()

    std::lock_guard<std::mutex> lock(mtx); // 创建 lock_guard 对象
    for (int i = 0; i < 10; ++i)
    
        data.push_back(i); 
        std::cout << "func1: " << i << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    


void func2()

    std::lock_guard<std::mutex> lock(mtx); // 创建 lock_guard 对象
    for (int i = 100; i < 110; ++i)
    
        data.push_back(i);
        std::cout << "func2: " << i << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    


int main()

    std::thread thrd1(func1);
    std::thread thrd2(func2);

    thrd1.join();
    thrd2.join();

    for (auto &i : data)
    
        std::cout << i << " ";
    
    std::cout << std::endl;
    return 0;


编译运行:

g++ test.cpp -lpthread && ./a.out

示例:用std::unique_lock加互斥锁并手动释放锁

在 C++ 中,互斥锁通常是通过 RAII 机制来保证自动释放,即在锁对象的生命周期结束时自动释放锁。但是,在某些情况下,可能需要手动释放互斥锁。在 C++11 中,可以通过 std::unique_lock::unlock() 方法来手动释放互斥锁。

下面是一个简单的示例代码,演示了如何手动释放互斥锁:

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

std::mutex g_mutex;
int count = 0;

void func()

    std::unique_lock<std::mutex> lock(g_mutex);
    std::cout << "Thread " << std::this_thread::get_id() << " acquired the lock." << std::endl;
    count++;
    std::cout << "Thread " << std::this_thread::get_id() << " count = " << count << std::endl;
    lock.unlock(); // 手动释放互斥锁  //如果不手动释放,锁会在函数结束时自动释放
    std::cout << "Thread " << std::this_thread::get_id() << " released the lock." << std::endl;
    //do somethine...
    std::this_thread::sleep_for(std::chrono::seconds(1));


int main()

    const int numThreads = 1000;

    std::thread threads[numThreads];
    for (int i = 0; i < numThreads; ++i) 
        threads[i] = std::thread(func);
    

    for (int i = 0; i < numThreads; ++i) 
        threads[i].join();
    

    std::cout << "final count = " << count << std::endl;

    return 0;


编译运行结果:

g++ test.cpp -lpthread && ./a.out

以上是关于linux C++互斥锁std::lock_guard(轻锁)std::unique_lock(重锁)区别的主要内容,如果未能解决你的问题,请参考以下文章

linux C++互斥锁std::lock_guard(轻锁)std::unique_lock(重锁)区别

在 C++ 中使用互斥锁和条件变量实现带有信号的监视器

C11线程管理:原子变量&单调函数

用于 Windows 的 C++ 互斥锁

C++封装互斥锁和基于RAII机制能自动解锁的互斥锁

如何在 Python 进程中访问由 C++ 进程创建的互斥锁?