std::scoped_lock` 和 `std::lock() ,condition_variable,promise

发布时间:2024年01月05日

std::scoped_lockstd::lock() 同时锁多个mutex

std::scoped_lockstd::lock() 都是 C++ 标准库中用于管理多个 std::mutex 对象的工具,但它们在使用方式和一些方面上存在一些区别。以下是它们的主要区别:

  1. 用法差异:

    • std::scoped_lock 是一个模板,你需要将要锁定的所有 std::mutex 作为参数传递给它的构造函数。它会在构造时锁定所有提供的互斥量,而在析构时自动释放这些锁。
    std::mutex mtx1;
    std::mutex mtx2;
    
    {
        std::scoped_lock lock(mtx1, mtx2);  // 锁定 mtx1 和 mtx2
        // 在这个作用域内,mtx1 和 mtx2 都已经被成功锁定
    }
    // 在这个作用域结束时,mtx1 和 mtx2 会被解锁支持RAII
    
    • std::lock() 是一个函数,接受任意数量的 std::mutex 参数,并在一次函数调用中尽可能地同时锁定所有提供的互斥量。这可以避免死锁,并且比分别调用 std::lock_guardstd::unique_lock 更高效。
    std::mutex mtx1;
    std::mutex mtx2;
    
     std::lock(mtx1, mtx2);  // 锁定 mtx1 和 mtx2
    //需要手动解锁,不支持RAII
    
  2. 死锁避免:

    • std::lock() 在一次函数调用中尝试锁定所有提供的互斥量,如果无法同时锁定,会产生 std::system_error 异常。因此,在使用 std::lock 时,确保所有互斥量都是可锁定的,否则会导致程序异常终止。
    • std::scoped_lock 在构造时就锁定了所有提供的互斥量,如果无法同时锁定会产生 std::system_error 异常。因此,在使用 std::lock 时,确保所有互斥量都是可锁定的,否则会导致程序异常终止。

在C++中,条件变量(Condition Variable)是用于线程间同步的一种机制。条件变量通常与互斥锁结合使用,用于实现线程的等待和唤醒机制,以确保线程在满足某些条件时才能执行。

常用的条件变量相关的类有 std::condition_variablestd::condition_variable_any。以下是简要介绍和使用条件变量的基本模式:

条件变量

std::condition_variable 使用示例:

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

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

void producer() {
    // 模拟生产数据
    std::this_thread::sleep_for(std::chrono::seconds(2));

    // 加锁,修改共享状态
    std::unique_lock<std::mutex> lock(mtx);
    dataReady = true;

    // 通知等待的线程
    cv.notify_one();
}

void consumer() {
    std::unique_lock<std::mutex> lock(mtx);

    // 等待条件变量通知
    cv.wait(lock, [] { return dataReady; });

    // 消费数据
    std::cout << "Data consumed." << std::endl;
}

int main() {
    std::thread producerThread(producer);
    std::thread consumerThread(consumer);

    producerThread.join();
    consumerThread.join();

    return 0;
}

在这个示例中,std::condition_variablestd::mutex 一起使用,cv.wait(lock, predicate) 用于等待条件变量的通知,而 cv.notify_one() 用于通知等待的线程。

要点:

  1. std::condition_variable 需要与 std::mutex 一起使用,以确保在条件变量上进行操作时的线程安全性。
  2. std::unique_lock 提供了更灵活的锁定和解锁操作,可以在需要的时候手动解锁,例如在等待条件变量时。
  3. cv.wait(lock, predicate) 中的 predicate 是一个可选的谓词函数,用于检查条件是否满足,如果条件不满足,则继续等待。

条件变量的正确使用可以确保线程在适当的时候等待和唤醒,以避免不必要的轮询和提高程序的效率。

线程异步和通信

std::promise异步调用

std::promisestd::future 是 C++11 标准库中提供的两个工具,用于在多线程之间传递数据或者实现异步操作。

  1. std::promise:

    • std::promise 用于在一个线程中存储一个值,然后在另一个线程中通过 std::future 获取这个值。一个 std::promise 对象关联一个 std::future 对象,后者可以在其他线程中被用来获取由 std::promise 对象设置的值。

    • std::promiseset_value 成员函数只能成功调用一次。一旦调用 set_valuestd::promise 对象就变得不能再用于设置新的值。

    • std::future 提供访问异步操作结果的机制 get() 阻塞等待promise set_value 的值

    • 示例:

      #include <iostream>
      #include <future>
      
      void setValue(std::promise<int>& prom) {
          prom.set_value(42);
      }
      
      int main() {
          std::promise<int> myPromise;
          std::future<int> myFuture = myPromise.get_future();
      
          std::thread t(setValue, std::ref(myPromise));
          t.join();
      
          int result = myFuture.get();
          std::cout << "Received value from promise: " << result << std::endl;
      
          return 0;
      }
      

    std::promise 用于在一个线程中设置值,然后通过与关联的 std::future 在另一个线程中获取这个值。std::future 则用于获取异步任务的结果。

  2. std::future:

    • std::future 用于从异步任务中获取值。std::future 对象可以通过与 std::promise 关联,或者通过 std::asyncstd::packaged_task 等方式创建。

    • 示例:

      #include <iostream>
      #include <future>
      
      int calculate() {
          return 21;
      }
      
      int main() {
          std::future<int> myFuture = std::async(std::launch::async, calculate);
      
          int result = myFuture.get();
          std::cout << "Result from future: " << result << std::endl;
      
          return 0;
      }
      

需要注意的是,std::promisestd::future 通常是成对使用的,但也可以通过其他方式创建 std::future 对象,比如使用 std::async

总体来说,std::promisestd::future 是 C++ 中实现简单异步编程的一种方便机制。

文章来源:https://blog.csdn.net/MrGong123/article/details/135395601
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。