• C++ 11 多线程下std::unique_lock与std::lock_guard的区别和用法


    这里主要介绍std::unique_lock与std::lock_guard的区别用法

    先说简单的

    一、std::lock_guard的用法

    std::lock_guard其实就是简单的RAII封装,在构造函数中进行加锁,析构函数中进行解锁,这样可以保证函数退出时,锁一定被释放。

    简单来说,就是防止开发者粗心大意,函数在分支中return时,忘记unlock操作导致后续操作全部被挂起甚至引发死锁情况的。

    用法如下:

    // lock_guard example
    #include <iostream>       // std::cout
    #include <thread>         // std::thread
    #include <mutex>          // std::mutex, std::lock_guard
    #include <stdexcept>      // std::logic_error
    
    std::mutex mtx;
    
    void print_even (int x) {
      if (x%2==0) std::cout << x << " is even
    ";
      else throw (std::logic_error("not even"));
    }
    
    void print_thread_id (int id) {
      try {
        // using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:
        std::lock_guard<std::mutex> lck (mtx);
        print_even(id);
      }
      catch (std::logic_error&) {
        std::cout << "[exception caught]
    ";
      }
    }
    
    int main ()
    {
      std::thread threads[10];
      // spawn 10 threads:
      for (int i=0; i<10; ++i)
        threads[i] = std::thread(print_thread_id,i+1);
    
      for (auto& th : threads) th.join();
    
      return 0;
    }

    二、std::unique_lock的用法

    std::unique_lock的功能相比std::lock_guard来说,就强大多了,是std::lock_guard的功能超集, 封装了各种加锁操作,阻塞的,非阻塞的,还可以结合条件变量一起使用,基本上对锁的各种操作都封装了,当然了,功能丰富是有代价的,那就是性能和内存开销都比std::lock_guard大得多,所以,需要有选择地使用。

    std::unique_lock也会在析构的时候自动解锁,所以说,是std::lock_guard的功能超集。

    看看std::unique_lock的构造函数,支持三种加锁模式:

    unique_lock( mutex_type& m, std::defer_lock_t t );   //延迟加锁
    unique_lock( mutex_type& m, std::try_to_lock_t t ); //尝试加锁
    unique_lock( mutex_type& m, std::adopt_lock_t t );   //马上加锁

    几个主要操作函数:

    lock()         //阻塞等待加锁
    try_lock()        // 非阻塞等待加锁
    try_lock_for()  //在一段时间内尝试加锁
    try_lock_until()   //在某个时间点之前尝试加锁

    接下来,给个例子:

    #include <mutex>
    #include <thread>
    #include <iostream>
    #include <vector>
    #include <chrono>
     
    int main()
    {
        int counter = 0;
        std::mutex counter_mutex;
        std::vector<std::thread> threads;
     
        auto worker_task = [&](int id) {
            std::unique_lock<std::mutex> lock(counter_mutex);
            ++counter;
            std::cout << id << ", initial counter: " << counter << '
    ';
            lock.unlock();
     
            // don't hold the lock while we simulate an expensive operation
            std::this_thread::sleep_for(std::chrono::seconds(1));
     
            lock.lock();
            ++counter;
            std::cout << id << ", final counter: " << counter << '
    ';
        };
     
        for (int i = 0; i < 10; ++i) threads.emplace_back(worker_task, i);
     
        for (auto &thread : threads) thread.join();
    }

    Output:

    0, initial counter: 1
    1, initial counter: 2
    2, initial counter: 3
    3, initial counter: 4
    4, initial counter: 5
    5, initial counter: 6
    6, initial counter: 7
    7, initial counter: 8
    8, initial counter: 9
    9, initial counter: 10
    6, final counter: 11
    3, final counter: 12
    4, final counter: 13
    2, final counter: 14
    5, final counter: 15
    0, final counter: 16
    1, final counter: 17
    7, final counter: 18
    9, final counter: 19
    8, final counter: 20
  • 相关阅读:
    Modernizr.js:为HTML5和CSS3而生!
    liunx 安装 phpstudy
    php 实现无限极分类
    网站邮箱端口
    android studio svn 创建分支
    卡在 构建 gradle 项目信息
    android 地图
    IllegalArgumentException: Unmatched braces in the pattern.
    软件设置开机启动
    输入网络凭据
  • 原文地址:https://www.cnblogs.com/moodlxs/p/10111843.html
Copyright © 2020-2023  润新知