您的位置:

深入剖析lock_guard和unique_lock

一、lock_guard实现

template 
class lock_guard
{
public:
    using mutex_type = Mutex;

    explicit lock_guard(mutex_type& mutex) : _mutex(mutex) 
    {
        _mutex.lock();
    }

    lock_guard(mutex_type& mutex, adopt_lock_t) : _mutex(mutex) {}

    ~lock_guard()
    {
        _mutex.unlock();
    }

    lock_guard() = delete;
    lock_guard(const lock_guard&) = delete;
    lock_guard& operator=(const lock_guard&) = delete;

private:
    mutex_type& _mutex;
};

  

lock_guard是一个RAII封装的锁,它强制在构造期间获得锁,在析构期间释放锁。lock_guard实现了一个“mutex妈妈”模式,在构造函数中获得锁,在析构函数中释放锁。lock_guard实现简单,使用简单。

二、c++ lock_guard

c++11和之前的标准库都已经提供了lock_guard。这意味着我们可以使用std::lock_guard来保护一个操作。std::mutex(或其他互斥对象)是一个RAII类,用于管理与互斥量相关的锁。lock_guard声明一个对象并使用std::adopt_lock的参数调用构造函数,可以将这个锁的管理权交给这个对象(这就是我们在构造函数中传递的参数)。当我们在这个对象的生命周期结束时,std::lock_guard会自动释放互斥量。

#include 
#include 
   
#include 
    

std::mutex m;

void foo()
{
    std::lock_guard
      lock(m);
    std::cout << "Thread " << std::this_thread::get_id() << " is executing foo()\n";
}

int main()
{
    std::thread t1(foo);
    std::thread t2(foo);

    t1.join();
    t2.join();
    return 0;
}

     
    
   
  

三、std lock_guard

lock_guard是std命名空间中包含的一个类,其目的是在构造时锁定互斥锁,在析构时释放锁。std::lock_guard的作用是保护比较短的互斥锁。当有必要保护一个对象或代码段,而这个保护不会被其他代码打断时,可以使用std::lock_guard来保护。

#include 
#include 
   
#include 
    

std::mutex m;

void foo()
{
    std::lock_guard
      lock(m);
    std::cout << "Thread " << std::this_thread::get_id() << " is executing foo()\n";
}

int main()
{
    std::thread t1(foo);
    std::thread t2(foo);

    t1.join();
    t2.join();
    return 0;
}

     
    
   
  

四、lock_guard与unique_lock

lock_guard和unique_lock都是互斥锁的RAII封装,但它们之间的区别有哪些呢?unique_lock有更多的功能,它支持C++11标准库的move语义,可以在传递所有权时使用,而lock_guard不支持。

unique_lock还可以在已经锁定的mutex上等待信号量,可以采用不同的锁调度策略,比如超时等。

#include 
#include 
   
#include 
    

std::mutex m;

void foo()
{
    std::unique_lock
      lock(m);
    std::cout << "Thread " << std::this_thread::get_id() << " is executing foo()\n";
}

int main()
{
    std::thread t1(foo);
    std::thread t2(foo);

    t1.join();
    t2.join();
    return 0;
}

     
    
   
  

在上面的代码中,我们使用unique_lock创建一个std::mutex对象的锁,foo()函数获得互斥锁,并在已经获得锁的情况下执行了一段代码,这意味着即使线程被中断,它也将在互斥锁上等待。

通过这篇文章,我们详细阐述了lock_guard和unique_lock的构造函数和应用。lock_guard和unique_lock是C++11提供的两种mutex的RAII封装,是C++中保证线程安全的重要手段,很少出现锁的泄漏以及锁的锁定时间过长。对于编写安全的并发代码是极其重要的。